add pgn-extract 22.11

This commit is contained in:
2024-01-22 07:30:05 +01:00
parent 1051ced4dc
commit abaff964ca
248 changed files with 63176 additions and 0 deletions

8
add-timectl.bash Executable file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
str='[TimeControl "3600"]'
str='[TimeControl "40/7200:20/3600:3600"]'
filein="$1"
fileout="$filein.new"
echo "in=$filein out=$fileout"
sed -e '/^\[Black ".*"\]/a '"$str" < "$filein" > "$fileout"

674
pgn-extract/COPYING Normal file
View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

135
pgn-extract/Makefile Normal file
View File

@@ -0,0 +1,135 @@
# Make file for the pgn-extract program.
#
# This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
# Copyright (C) 1994-2022 David J. Barnes
#
# pgn-extract is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pgn-extract is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
#
# David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
# https://www.cs.kent.ac.uk/people/staff/djb/
OBJS=grammar.o lex.o map.o decode.o moves.o lists.o apply.o output.o eco.o \
lines.o end.o main.o hashing.o argsfile.o mymalloc.o fenmatcher.o \
taglines.o zobrist.o
DEBUGINFO=-g
# These flags are particularly severe on checking warnings.
# It may be that they are not all appropriate to your environment.
# For instance, not all environments have prototypes available for
# the standard library functions.
# Linux users might need to add -D__linux__ to these in order to
# use strcasecmp instead of strcmpi (cf output.c)
# Mac OS X users might need to add -D__unix__ to CFLAGS
# and use CC=cc or CC=gcc
OPTIMISE=-O3
CFLAGS+=-c -pedantic -Wall -Wshadow -Wformat -Wpointer-arith \
-Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings \
-Wsign-compare -Wimplicit-function-declaration $(DEBUGINFO) \
-I/usr/local/lib/ansi-include -std=c99 \
$(CPPFLAGS) \
$(OPTIMISE)
CC=gcc
LIBS=-lm
# AIX 3.2 Users might like to use these alternatives for CFLAGS and CC.
# Thanks to Erol Basturk for providing them.
AIX_CFLAGS=-c -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_ALL_SOURCE
AIX_CC=xlc
pgn-extract : $(OBJS)
$(CC) $(DEBUGINFO) $(ORIGCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o pgn-extract
purify : $(OBJS)
purify $(CC) $(DEBUGINFO) $(OBJS) -o pgn-extract
clean:
rm -f core pgn-extract *.o
mymalloc.o : mymalloc.c mymalloc.h
$(CC) $(CFLAGS) mymalloc.c
apply.o : apply.c defs.h lex.h grammar.h typedef.h map.h bool.h apply.h taglist.h\
eco.h decode.h moves.h hashing.h mymalloc.h output.h fenmatcher.h\
zobrist.h
$(CC) $(CFLAGS) apply.c
argsfile.o : argsfile.c argsfile.h bool.h defs.h typedef.h lines.h \
taglist.h tokens.h lex.h taglines.h moves.h eco.h apply.h output.h \
lists.h mymalloc.h fenmatcher.h
$(CC) $(CFLAGS) argsfile.c
decode.o : decode.c defs.h typedef.h taglist.h lex.h bool.h decode.h lists.h \
tokens.h mymalloc.h
$(CC) $(CFLAGS) decode.c
eco.o : eco.c defs.h lex.h typedef.h map.h bool.h eco.h taglist.h apply.h \
mymalloc.h
$(CC) $(CFLAGS) eco.c
end.o : end.c end.h bool.h defs.h typedef.h lines.h tokens.h lex.h mymalloc.h \
apply.h grammar.h
$(CC) $(CFLAGS) end.c
grammar.o : grammar.c bool.h defs.h typedef.h lex.h taglist.h map.h lists.h\
moves.h apply.h output.h tokens.h eco.h end.h grammar.h hashing.h \
mymalloc.h
$(CC) $(CFLAGS) grammar.c
hashing.o : hashing.c hashing.h bool.h defs.h typedef.h tokens.h\
taglist.h lex.h mymalloc.h zobrist.h
$(CC) $(CFLAGS) hashing.c
lex.o : lex.c bool.h defs.h typedef.h tokens.h taglist.h map.h\
lists.h decode.h moves.h lines.h grammar.h mymalloc.h apply.h\
output.h
$(CC) $(CFLAGS) lex.c
lines.o : lines.c bool.h lines.h mymalloc.h
$(CC) $(CFLAGS) lines.c
lists.o : lists.c lists.h taglist.h bool.h defs.h typedef.h mymalloc.h moves.h
$(CC) $(CFLAGS) lists.c
main.o : main.c bool.h defs.h typedef.h tokens.h taglist.h lex.h moves.h\
map.h lists.h output.h end.h grammar.h hashing.h \
argsfile.h mymalloc.h
$(CC) $(CFLAGS) main.c
map.o : map.c defs.h lex.h typedef.h map.h bool.h decode.h taglist.h \
mymalloc.h
$(CC) $(CFLAGS) map.c
moves.o : moves.c defs.h typedef.h lex.h bool.h map.h lists.h moves.h apply.h\
lines.h taglist.h mymalloc.h fenmatcher.h
$(CC) $(CFLAGS) moves.c
fenmatcher.o : fenmatcher.c grammar.h apply.h bool.h defs.h fenmatcher.h mymalloc.h\
typedef.h end.h
$(CC) $(CFLAGS) fenmatcher.c
output.o : output.c output.h taglist.h bool.h typedef.h defs.h lex.h grammar.h\
apply.h mymalloc.h
$(CC) $(CFLAGS) output.c
taglines.o : taglines.c bool.h defs.h typedef.h tokens.h taglist.h lex.h lines.h \
lists.h moves.h output.h taglines.h
$(CC) $(CFLAGS) taglines.c
zobrist.o : zobrist.c zobrist.h bool.h defs.h typedef.h apply.h decode.h grammar.h
$(CC) $(CFLAGS) zobrist.c

View File

@@ -0,0 +1,140 @@
# Make file for the pgn-extract program.
#
# This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
# Copyright (C) 1994-2022 David J. Barnes
#
# pgn-extract is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pgn-extract is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
#
# David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
# https://www.cs.kent.ac.uk/people/staff/djb/
OBJS=grammar.o lex.o map.o decode.o moves.o lists.o apply.o output.o eco.o \
lines.o end.o main.o hashing.o argsfile.o mymalloc.o fenmatcher.o \
taglines.o zobrist.o
DEBUGINFO=-g
# These flags are particularly severe on checking warnings.
# It may be that they are not all appropriate to your environment.
# For instance, not all environments have prototypes available for
# the standard library functions.
# Linux users might need to add -D__linux__ to these in order to
# use strcasecmp instead of strcmpi (cf output.c)
# Mac OS X users might need to add -D__unix__ to CFLAGS
# and use CC=cc or CC=gcc
OPTIMISE=-O3
CFLAGS+=-c -pedantic -Wall -Wshadow -Wformat -Wpointer-arith \
-Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings \
-Wsign-compare -Wimplicit-function-declaration $(DEBUGINFO) \
-I/usr/local/lib/ansi-include -std=c99 \
$(CPPFLAGS) \
$(OPTIMISE)
CC=gcc
# Libraries required for a static link of regex.
LIBS=-lm /mingw64/lib/libregex.a \
/mingw64/lib/libtre.a\
/mingw64/lib/libintl.a \
/mingw64/lib/libiconv.a
LDFLAGS=
# AIX 3.2 Users might like to use these alternatives for CFLAGS and CC.
# Thanks to Erol Basturk for providing them.
AIX_CFLAGS=-c -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_ALL_SOURCE
AIX_CC=xlc
pgn-extract : $(OBJS)
$(CC) $(DEBUGINFO) $(ORIGCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o pgn-extract
purify : $(OBJS)
purify $(CC) $(DEBUGINFO) $(OBJS) -o pgn-extract
clean:
rm -f core pgn-extract *.o
mymalloc.o : mymalloc.c mymalloc.h
$(CC) $(CFLAGS) mymalloc.c
apply.o : apply.c defs.h lex.h grammar.h typedef.h map.h bool.h apply.h taglist.h\
eco.h decode.h moves.h hashing.h mymalloc.h output.h fenmatcher.h\
zobrist.h
$(CC) $(CFLAGS) apply.c
argsfile.o : argsfile.c argsfile.h bool.h defs.h typedef.h lines.h \
taglist.h tokens.h lex.h taglines.h moves.h eco.h apply.h output.h \
lists.h mymalloc.h fenmatcher.h
$(CC) $(CFLAGS) argsfile.c
decode.o : decode.c defs.h typedef.h taglist.h lex.h bool.h decode.h lists.h \
tokens.h mymalloc.h
$(CC) $(CFLAGS) decode.c
eco.o : eco.c defs.h lex.h typedef.h map.h bool.h eco.h taglist.h apply.h \
mymalloc.h
$(CC) $(CFLAGS) eco.c
end.o : end.c end.h bool.h defs.h typedef.h lines.h tokens.h lex.h mymalloc.h \
apply.h grammar.h
$(CC) $(CFLAGS) end.c
grammar.o : grammar.c bool.h defs.h typedef.h lex.h taglist.h map.h lists.h\
moves.h apply.h output.h tokens.h eco.h end.h grammar.h hashing.h \
mymalloc.h
$(CC) $(CFLAGS) grammar.c
hashing.o : hashing.c hashing.h bool.h defs.h typedef.h tokens.h\
taglist.h lex.h mymalloc.h zobrist.h
$(CC) $(CFLAGS) hashing.c
lex.o : lex.c bool.h defs.h typedef.h tokens.h taglist.h map.h\
lists.h decode.h moves.h lines.h grammar.h mymalloc.h apply.h\
output.h
$(CC) $(CFLAGS) lex.c
lines.o : lines.c bool.h lines.h mymalloc.h
$(CC) $(CFLAGS) lines.c
lists.o : lists.c lists.h taglist.h bool.h defs.h typedef.h mymalloc.h moves.h
$(CC) $(CFLAGS) lists.c
main.o : main.c bool.h defs.h typedef.h tokens.h taglist.h lex.h moves.h\
map.h lists.h output.h end.h grammar.h hashing.h \
argsfile.h mymalloc.h
$(CC) $(CFLAGS) main.c
map.o : map.c defs.h lex.h typedef.h map.h bool.h decode.h taglist.h \
mymalloc.h
$(CC) $(CFLAGS) map.c
moves.o : moves.c defs.h typedef.h lex.h bool.h map.h lists.h moves.h apply.h\
lines.h taglist.h mymalloc.h fenmatcher.h
$(CC) $(CFLAGS) moves.c
fenmatcher.o : fenmatcher.c grammar.h apply.h bool.h defs.h fenmatcher.h mymalloc.h\
typedef.h end.h
$(CC) $(CFLAGS) fenmatcher.c
output.o : output.c output.h taglist.h bool.h typedef.h defs.h lex.h grammar.h\
apply.h mymalloc.h
$(CC) $(CFLAGS) output.c
taglines.o : taglines.c bool.h defs.h typedef.h tokens.h taglist.h lex.h lines.h \
lists.h moves.h output.h taglines.h
$(CC) $(CFLAGS) taglines.c
zobrist.o : zobrist.c zobrist.h bool.h defs.h typedef.h apply.h decode.h grammar.h
$(CC) $(CFLAGS) zobrist.c

2790
pgn-extract/apply.c Normal file

File diff suppressed because it is too large Load Diff

46
pgn-extract/apply.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef APPLY_H
#define APPLY_H
void add_fen_castling(Game *game_details, Board *board);
Boolean apply_move_list(Game *game_details,unsigned *plycount, unsigned max_depth);
Boolean apply_move(Move *move_details, Board *board);
Board *apply_eco_move_list(Game *game_details,unsigned *number_of_half_moves);
void build_basic_EPD_string(const Board *board,char *fen);
char coloured_piece_to_SAN_letter(Piece coloured_piece);
Piece convert_FEN_char_to_piece(char c);
CommentList *create_match_comment(const Board *board);
void free_board(Board *board);
char *get_FEN_string(const Board *board);
Board *new_fen_board(const char *fen);
Board *new_game_board(const char *fen);
const char *piece_str(Piece piece);
Board *rewrite_game(Game *game_details);
char SAN_piece_letter(Piece piece);
Boolean save_polyglot_hashcode(const char *value);
/* letters should contain a string of the form: "PNBRQK" */
void set_output_piece_characters(const char *letters);
void store_hash_value(Move *move_details,const char *fen);
#endif // APPLY_H

1812
pgn-extract/argsfile.c Normal file

File diff suppressed because it is too large Load Diff

74
pgn-extract/argsfile.h Normal file
View File

@@ -0,0 +1,74 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Classifications for the arguments allowed in an argsfile. */
#ifndef ARGSFILE_H
#define ARGSFILE_H
typedef enum {
SEVEN_TAG_ROSTER_ARGUMENT = '7',
GAMES_PER_FILE_ARGUMENT = '#',
ALTERNATIVE_HELP_ARGUMENT = '?',
LONG_FORM_ARGUMENT = '-',
APPEND_TO_OUTPUT_FILE_ARGUMENT = 'a',
MOVE_BOUNDS_ARGUMENT = 'b',
CHECK_FILE_ARGUMENT = 'c',
DUPLICATES_FILE_ARGUMENT = 'd',
USE_ECO_FILE_ARGUMENT = 'e',
FILE_OF_FILES_ARGUMENT = 'f',
HELP_ARGUMENT = 'h',
WRITE_TO_LOG_FILE_ARGUMENT = 'l',
NON_MATCHING_GAMES_ARGUMENT = 'n',
WRITE_TO_OUTPUT_FILE_ARGUMENT = 'o',
PLY_BOUNDS_ARGUMENT = 'p',
CHECK_ONLY_ARGUMENT = 'r',
KEEP_SILENT_ARGUMENT = 's',
TAGS_ARGUMENT = 't',
MOVES_ARGUMENT = 'v',
LINE_WIDTH_ARGUMENT = 'w',
POSITIONS_ARGUMENT = 'x',
ENDINGS_COLOURED_ARGUMENT = 'y',
ENDINGS_ARGUMENT = 'z',
FILE_OF_ARGUMENTS_ARGUMENT = 'A',
DONT_KEEP_COMMENTS_ARGUMENT = 'C',
DONT_KEEP_DUPLICATES_ARGUMENT = 'D',
ECO_OUTPUT_LEVEL_ARGUMENT = 'E',
OUTPUT_FEN_STRING_ARGUMENT = 'F',
HASHCODE_MATCH_ARGUMENT = 'H',
APPEND_TO_LOG_FILE_ARGUMENT = 'L',
MATCH_CHECKMATE_ARGUMENT = 'M',
DONT_KEEP_NAGS_ARGUMENT = 'N',
DONT_MATCH_PERMUTATIONS_ARGUMENT = 'P',
TAG_ROSTER_ARGUMENT = 'R',
USE_SOUNDEX_ARGUMENT = 'S',
TAG_EXTRACTION_ARGUMENT = 'T',
SUPPRESS_ORIGINALS_ARGUMENT = 'U',
DONT_KEEP_VARIATIONS_ARGUMENT = 'V',
OUTPUT_FORMAT_ARGUMENT = 'W',
USE_VIRTUAL_HASH_TABLE_ARGUMENT = 'Z',
NO_ARGUMENT_MATCH = '\0' /* No argument match. */
} ArgType;
void process_argument(char arg_letter,const char *associated_value);
int process_long_form_argument(const char *argument, const char *associated_value);
#endif // ARGSFILE_H

31
pgn-extract/bool.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Define a type for Booleans.
* This is used everywhere.
*/
#ifndef BOOL_H
#define BOOL_H
typedef enum { FALSE, TRUE } Boolean;
#endif // BOOL_H

486
pgn-extract/changes.html Normal file
View File

@@ -0,0 +1,486 @@
<head>
<title>Change History</title>
<link rel="author" href="mailto:d.j.barnes@kent.ac.uk">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<meta name="Author" content="David J. Barnes">
<meta name="Description" content="Change history for pgn-extract">
<meta name="Keywords"
content="pgn-extract change history">
<link href="style.css" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<div id="body">
<div id="page-wrapper">
<div id="page">
<h2>Change History</h2>
<ul>
<li>10th August 2022: Bug fix with -z for failure to match the final position and not
necessarily marking the first match in a game when there are multiple matches.
<li>7th August 2022: Bug fix for -z when only one side's pieces are listed.
<li>27th June 2022: --firstgame and --gamelimit added. Suggested by Peter Stein.
<li>23rd June 2022: Regular expressions added to tag matching via -t. Suggested by Peter
Stein.
<li>18th May 2022: --seventyfive added.
<li>17th May 2022: --repetition5 added.
<li>16th May 2022: Multiple numeric matches of a single tag with -t now
require all matches to be true. This allows selection of ranges of values
via &lt; and &gt; operators, for instance.
Floating-point numerical values are accepted.
<li>3rd May 2022: Bug fix for failure to clear a pointer to freed memory.
<li>27th Mar 2022: Relational operator (>, <, etc.) may be used to match
any wholly numeric tag values via the -t flag.
<li>23rd Feb 2022: Bug fix for material matches where games involve promotion.
<li>17th Feb 2022: Added recognition of some en passant indicators in the input. They are deleted
in the output version.
<li>26th Jan 2022: Added recognition of single-line comments. I have no idea why these escaped my
attention over the past 27 years!
<br>Fixed inconsistent conversion of polyglot hashcodes shorter than 16 digits, and output hashcodes
with leading zeros where appropriate. The fix affected correct operation of the -H option.
<br>Replaced nonsense Result tags with *.
<br>Fixed incorrect TotalPlyCount when --totalplycount and --splitvariants are used together.
<br>Thanks for Robert Gamble for highlighting these issues.
<li>18th Jan 2022: Bug fix to --evaluation that counted illegal ep moves in the Shannon evaluation.
<li>28 Dec 2021: Edits to the index to make it a little more structured.
<li>24th Nov 2021: Added -Wfen.
<li>16th July 2021: Added --deletesamesetup.
<li>25th June 2021: Extended matching of TimeControl to include the formats
of sudden death and sandclock.
<li>19th June 2021: Added --addfencastling following a suggestion from
David Barlow.
<li>4th Apr 2021: Added --detag following a suggestion by Gabriele Battaglia.
<li>2nd Mar 2021: Make duplicate suppression work with input from stdin. Added --minply, --maxply,
--minmoves, --maxmoves as clearer alternatives to -p and -b.
<li>27th Jan 2021: Bug fix to --fixtagstrings.
<li>3rd Jan 2021: Added --linenumbers following a suggestion by Ejner Borgbjerg.
<li>8th Nov 2020: Added --fixtagstrings.
<li>7th Nov 2020: Date matches with -t and -T extended to match on month and day as well as year.
<li>7th Oct 2020: Added --wtm and --btm.
<li>25th Jul 2020: Added limited relational TimeControl matching with -t following
a suggestion by Erwin Wouterson.
<li>2nd Jul 2020: Added missing 'ep' for en passant moves with -Wxlalg and -Wxolalg.
<li>12th Feb 2020: Bug fix to eliminate illegal pawn moves in long algebraic notation.
<li>13th Oct 2019: Suppressed repeated error message with malformed dates when matching a Date tag with a relational operator.
<li>31st Jul 2019: Added --startply.
<li>21st Jun 2019: Added --fenpattern, --fenpatterni, --materialy and --materialz as command-line arguments.
<li>9th May 2019: Delete NAGs appearing before the first move of a game. $220 is
sometimes used (e.g., by ChessPad) as a print-board indicator.
<li>22nd Apr 2019: Improved --repetition so that it does not give false positives when
castling rights or who is to move are different.
<p>Retain next move number rather than resetting to 1 with --dropply and --dropbefore.
<li>14th Apr 2019: Fixed a memory error in v18-10 that occurred when a positional match was found but the moves of the game were invalid.
<li>28th Mar 2019: Added --xroster to suppress tags that are not required with -R.
<li>13th Nov 2018: Missing SetUp tags no longer elicit an error message as this contravention of the standard is so common.
<li>28th Oct 2018: Negative value accepted with --dropply to indicates plies to be
retained at the end of the game.
<li>18th Oct 2018: open game files in binary mode to cope with the Ctrl
characters that appear in some.
<li>17th Oct 2018: Accept Z0 as an alternative to --.</li>
<li>13th Oct 2018: Added --dropbefore as a result of a suggestion by Josip Salai.
Fixed missing SetUp tag with --dropply.
Fixed -H to work with 32-bit Windows.</li>
<li>7th Oct 2018: Added -y.</li>
<li>19th Aug 2018: Fixed a memory leak with -z.</li>
<li>11th July 2018: Added the MatchLabel tag and FENPatternI matching
with -t after a suggestion by Hedinn Steingrimsson.
In addition, significantly improved the efficiency of FENPattern
matches.</li>
<li>3rd July 2018: Added the MaterialMatch tag with -z after a suggestion
by Hedinn Steingrimsson.</li>
<li>23rd Apr 2018: With -R, include tags in the output that are not explicitly
listed in the roster order. This aligns the behaviour with the documentation.</li>
<li>9th Feb 2018: Suppress warning for null moves when --allownullmoves is used.
With --fixresulttags, prefer the terminating result if either it or the result
tag is "*".</li>
<li>29th Dec 2017: Corrected failure to OR rather than AND the pseudo Elo
tag used with -t.</li>
<li>17th Dec 2017: Accepted multiple NAG comment pairs after a move.
If NAGs are suppressed then the associated comments are retained.</li>
<li>30th Nov 2017: Added --nestedcomments.</li>
<li>12th Nov 2017: Added --dropply after a suggestion by Heiko Bruns.</li>
<li>5th Oct 2017: Only require "960" in Variant tag strings for
Chess960 games.</li>
<li>23rd Sep 2017: Added the previously documented, but
unimplemented --underpromotion.</li>
<li>3rd Sep 2017: Bug fix for zero-move games which were not being
followed by a blank line.</li>
<li>26th July 2017: --matchplylimit added following a suggestion by James Ward.</li>
<li>23rd July 2017: Bug fix for --splitvariants.</li>
<li>21st July 2017: Added --nobadresults to suppress games with inconsistent
result indications.
Fixed failure to correct terminating result with --fixresulttags.
Added --allownullmoves.</li>
<li>15th July 2017: Added -Tf for FEN pattern matching.</li>
<li>8th July 2017: Added --plycount. With -z, use a FEN tag (if present) to count
the number of pieces.</li>
<li>6th July 2017: Adjusted -z to work correctly with a position stability value of 0.
Implemented the suggestion of Josip Salai that that FEN as the marker with --markmatches
should be interpreted as a request to output the FEN encoding of the match position.</li>
<li>28th June 2017: Added a c1 comment to -Wepd output to record the game's result.
Added the requirement that the Variant tag contain the string "chess 960" to be
considered as Chess960 games on output. This primarily affects encoding of castling
moves in long-algebraic notation.</li>
<li>6th June 2017: Added a second number to the -# flag to control file numbering.</li>
<li>4th June 2017: Chess960 long algebraic castling notation accommodated
on both input and output. This is where castling is indicated by specifying
the Rook's column as the destination for the King.</li>
<li>2nd June 2017: With --fixresulttags don't report inconsistent results that
can be fixed.</li>
<li>21st May 2017: Added --commentlines after a suggestion
by Gabriele Battaglia.</li>
<li>21st April 2017: Optional limiting depth added to --splitvariants.</li>
<li>7th April 2017: License updated to version 3 of the GPL.</li>
<li>31st March 2017: Added --splitvariants after a suggestion by Vladimir Volovich
to add functionality found in pgnsplit.</li>
<li>19th February 2017: Extended --selectonly and added --skipmatching after
a suggestion by Folkert van Heusden.</li>
<li>16th February 2017: Fixed runtime failure when -x and -n were used together.
Added missing SetUp tag when a FEN tag is present.
Correct "1/2" in a Result tag to "1/2-1/2".
Added explicit Q promotion when unspecified.
Fixed lack of output with -W (i.e., output as source).</li>
<li>29th January 2017: Added --hashcomments to add a comment containing
a polyglot hash code after each move. Added -H for Zobrist polyglot hash
matches.</li>
<li>Added text after -F for FEN-position output at arbitrary positions and not simply
at the end of a game. Suggested by Josip Salai.</li>
<li>22nd January 2017: Added --stopafter.</li>
<li>20th January 2017: Added --nosetuptags and --onlysetuptags following a
discussion with Mike Crockett. Added -p[elu] for finer control of game
length matching than provided by -b.</li>
<li>14th January 2017: Fixed --fuzzydepth.</li>
<li>9th January 2017: Improved the efficiency of (lack of) stalemate detection.</li>
<li>1st January 2017: Added --fixresulttags for conflicts between the game termination
and the result tag.
Source code rewrites of function names for more consistent naming.</li>
<li>8th November 2016: Allows 'b' as a trailing promotion character, previously disallowed.</li>
<li>3rd September 2016: Added --quiescent for position quiescence after a suggestion from
Mike Crockett.</li>
<li>17th April 2016: Added --tagsubstr for substring matches on tags.</li>
<li>4th March 2016: Added --quiet to suppress the number of games processed, as an extension of -s.
(Suggested by Norm Pollock.)</li>
<li>21st November 2015: Added recognition of Chess960 FEN encodings and application of its
castling rules.</li>
<li>16th October 2015: Added --fifty, --repetition, and warnings about inconsistent results in tags on
checkmate and stalemate after suggestions by Norm Pollock.</li>
<li>6th May 2015: Fixed errors in the half-move clock on castling and pawn promotion, thanks
to Brandon RichardWebster.</li>
<li>23rd Mar 2015: Added --nofauxep after a suggestion by Norm Pollock.</li>
<li>21st Mar 2015: Fixed off-by-one in move number output with -F when white-to-move.</li>
<li>20th Mar 2015: Added -Wxlalg at the suggestion of Bruce Ramsey.</li>
<li>8th Jan 2015: Fixed bug in game counting with -#.
Suppressed games with null moves (--) in the main line.</li>
<li>28th October 2014. Added --selectonly after a suggestion by Francis Steen.</li>
<li>2nd September 2014. Corrected an error in the generation of hashcodes
when a promotion is made.</li>
<li>31st May 2014. Added --addhashcode.</li>
<li>25th May 2014. Added --totalplycount for Erich K&ouml;rber.</li>
<li>5th March 2014. Added --keepbroken to allow broken games to be output.
Added at the request of Mark Crowther primarily to deal with the problem of live
recording where the kings are moved to the centre of the board at the end of
a game and erroneously included in the score.</li>
<li>6th September 2013. Corrected failure to 'or' together multiple
dates with -T and -t.</li>
<li>16th May 2013. Corrected an error in the whole-move number in
FEN output, thanks to Vincent Fleuranceau.</li>
<li>14th May 2013. Null move notation (--) in variations recognised.</li>
<li>16th April 2013. Added --fuzzydepth. This is due to Owen D. Lyne who
requested this functionality years ago - sorry for taking so long, Owen!</li>
<li>11th April 2013. Added -Wuci.</li>
<li>29th March 2013. Added --version.</li>
<li>26th March 2013. Fixed crash when a string to be output is longer than the output line length.</li>
<li>12th March 2013. Added long-form versions of -a, -c, -d and -o:
--append, --checkfile, --duplicates and --output.</li>
<li>9th February 2013. Added pattern matching based on
FEN descriptions and --markmatches for JS.</li>
<li>23rd December 2012. Added --fencomments for Tyler Eaves.</li>
<li>2nd December 2012. Allowed 0 for --plylimit.</li>
<li>22nd September 2008. Added --stalemate for Wieland Belka.</li>
<li>15th September 2008. Added --nochecks and fixed -A so that it
handles long-form arguments properly.</li>
<li>22nd December 2007. Added --notags, --plylimit, --nomovenumbers and
--noresults after a suggestion by Wieland Belka to be able to create opening books.</li>
<br>Added --evaluation for Folkert van Heusden.</li>
<br>Added --stalemate for Norm Pollock.</li>
<br>Added calculation of the half-move clock to FEN strings.</li>
<br>Most of the arguments taking filenames can now be separated from
the filename with a space.</li>
<br>Gradually adding long-form alternatives for arguments, e.g.
--seven, --notags, etc.</li>
<li>24th April 2007. Fixed a bug with mate annotation. Added the -M flag for
checkmate matches, which is due to Richard Jones.</li>
<li>19th October 2005. Added language-specific letters to -Welalg
following a suggestion from Folkert van Heusden.</li>
<li>1st May 2004: Fixed an error with ECO classification that
was causing the file list to be out of sync.</li>
<li>29th April 2004: Buffered game text before outputting it,
so that trailing spaces on lines (which violate the PGN spec)
can be deleted.<br>
Games with zero moves are now acceptable.</li>
<li>26th April 2004: Slight modification to one of the hashing
values made in order to try to avoid clashes in ECO matches.
ECO matches now have a discretion of up to 6 half moves.</li>
<li>13th February 2002: Added -Welalg as an output format following
a suggestion from Rafal Furdzik.</li>
<li>27th March 2001
<ul>
<li>Added output of EPD via -Wepd.
<li>Fixed a long standing error in FEN castling rights. These were
not being withdrawn if a Rook was captured on its home square.
Pointed out by Karl-Martin Skontorp, who also provided the
incentive to add -Wepd.
</ul></li>
<li>26th April 2000
Added the -R flag for tag ordering.</li>
<li>22nd April 2000
Completed implementation of -A to work with all flags.</li>
<li>21st April 2000
<ul>
<li>Added the -F flag.
<li>Added support for reading Russian source files.
</ul></li>
<li>11th April 2000
<ul>
<li>Added the -A flag.
<li>Extended usage of -Wsan to support output in different languages.
<li>Usage of -e with -7 retains an ECO tag in matched games.
<li>FEN tags with the -t flag are used as positional matches
(equivalent to -x matches).
<li>Non-standard tags are now retained in game output.
</ul></li>
<li>12th January 2000
C compiler with Red Hat Linux 6 was no longer happy with
static initialisations involving stdin, stdout and stderr.
Changes made to lex.c and main.c to work around this.
Pointed out by Mladen Bestvina.</li>
<li>18th October 1999
Numbers greater than 3 allowed with -E, at the request of Owen Lyne.</li>
<li>15th December 1997
Treat \r as WHITESPACE (for DOS files).</li>
<li>8th June 1997
Added -b flag to set bounds on the number of moves in a game to
be matched.</li>
<li>2nd May 1997
Corrected small error when strings were not terminated properly.
In tags, this resulted in the corrected tag ending in ]"] instead
of "].</li>
<li>17th February 1997
Added a little more error recovery.</li>
<li>15th November 1996
Added -Z.</li>
<li>23rd Sep 1996
It is no longer necessary to omit move numbers from the variations
files (-v and -x). This makes it easier to cut and paste games
of interest into these files.</li>
<li>28th Jun 1996
It is no longer necessary to terminate the tag file (-t).
Relational operators added in the tag file (-t).
Added -E flag.</li>
<li>7th May 1996
Corrected failure to make ECO classification when combined with -x.
Added lalg and halg as long algebraic output formats.</li>
<li>9th Oct 1995
Add -#</li>
<li>25th Sep 1995:
Default to reading stdin if no file arguments are provided.</li>
<li>24th Jul 1995:
Added setup from FEN tags.</li>
<li>18th Jul 1995:
<ul>
<li>Added material balance matches with -z.
<li>Added 'L' as a minor piece letter in ending files.
</ul></li>
<li>14th Jul 1995:
Made the order of arguments immaterial.</li>
<li>5th Jul 1995:
<ul>
<li>Added ECO classification with -e.
<li>Fixed false partial substring matches with -v, e.g. textual
variation move Nc6 is now no longer matched by game move c6.
</ul></li>
<li>22nd Mar 1995:
Made permutation matching with -v the default and added -P
to suppress it.</li>
<li>Jan 1995: Added -n and -L.</li>
<li>17th Nov 1994: Liberated the program from using YACC and Lex.</li>
<li>13th Oct 1994: Released test version with ChessMaster output.</li>
<li>20th Sep 1994: Added move rewriting and -W flag.</li>
<li>7th Sep 1994: Added -D flag.</li>
<li>6th Sep 1994: Added -C and -V flags and soundex matching.</li>
<li>5th Sep 1994:
<ul>
<li>Integrated the positional variation code from a separately
developed program.
<li>Added -N flag.
<li>Added ! to the textual variation syntax.
<li>Removed the writing to extract.pgn that was present in an
earlier unreleased version.
<li>Added -d flag.
</ul></li>
<li>8th Jul 1994:
<ul>
<li>Added -o flag.
<li>Discarded writing to standard output in DOS version because of
extensive problems trying to make this work with redirected
output. Instead, output is written to the file extract.pgn.
</ul></li>
<li>6th Jul 1994: Added -7 flag.</li>
<li>9th May 1994: Added -p flag for variation permutations.</li>
<li>6th May 1994: Added * as a don't-care move in variations files.</li>
<li>26th Apr 1994: Added the -t flag for files of extraction criteria.</li>
<li>25th Apr 1994: Added the -T flag for extraction criteria.</li>
<li>22nd Apr 1994: Added the -f flag for handling lists of PGN files.</li>
<li>13th Apr 1994:
<ul>
<li>Cleaned up the game-length determination by reading/writing files
in binary-mode.
<li>Added -a flag for appending to existing .pgn files.
<li>Added multiple input files.
<li>Made verbose output the default behaviour.
</ul></li>
</ul>
</div>
</div>
</div>
</body>

21
pgn-extract/copyright Normal file
View File

@@ -0,0 +1,21 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/

670
pgn-extract/decode.c Normal file
View File

@@ -0,0 +1,670 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* This file contains functions concerned with decoding
* the original text of a move in order to determine:
* which MoveClass it is in;
* any start and end square information.
* It extracts this information purely from the move text
* rather than analysing the move within the context of
* a board position.
* This information is later refined by the semantic analysis
* phase of the program as part of the checking of a game score.
*/
#include <stdio.h>
#include <string.h>
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "decode.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
/* Does the character represent a column of the board? */
Boolean
is_col(char c)
{
return (FIRSTCOL <= c) && (c <= LASTCOL);
}
/* Does the character represent a rank of the board? */
Boolean
is_rank(char c)
{
return (FIRSTRANK <= c) && (c <= LASTRANK);
}
/* What kind of piece is *move likely to represent?
* Note, the provision for double-character pieces,
* like a Russian King, means we need access to a
* string rather than a single char.
*/
Piece
is_piece(const unsigned char *move)
{
Piece piece = EMPTY;
switch (*move) {
case 'K': case 'k':
piece = KING;
break;
case 'Q': case 'q':
case 'D': /* Dutch/German. */
case RUSSIAN_QUEEN:
piece = QUEEN;
break;
case 'R': case 'r':
case 'T': /* Dutch/German. */
case RUSSIAN_ROOK:
piece = ROOK;
break;
case 'N': case 'n':
case 'P': /* Dutch. */
case 'S': /* German. */
piece = KNIGHT;
break;
case 'B':
case 'L': /* Dutch/German. */
case RUSSIAN_BISHOP:
/* Lower case 'b' is most likely to be a pawn reference. */
piece = BISHOP;
break;
case RUSSIAN_KNIGHT_OR_KING:
if (RUSSIAN_PIECE_CHECK(*(move + 1)) == RUSSIAN_KING_SECOND_LETTER) {
piece = KING;
}
else {
piece = KNIGHT;
}
break;
}
return piece;
}
/* Is the symbol a capturing one?
* In fact, this is used to recognise any general separator
* between two parts of a move, e.g.:
* Nxc3, e2-e4, etc.
*/
static Boolean
is_capture(char c)
{
return (c == 'x') || (c == 'X') || (c == ':') || (c == '-');
}
static Boolean
is_castling_character(char c)
{
return (c == 'O') || (c == '0') || (c == 'o');
}
Boolean
is_check(char c)
{
return (c == '+') || (c == '#');
}
/* Allocate space in which to return the information that
* has been gleaned from the move.
*/
Move *
new_move_structure(void)
{
Move *move = (Move *) malloc_or_die(sizeof (Move));
move->terminating_result = NULL;
move->piece_to_move = EMPTY;
move->captured_piece = EMPTY;
move->promoted_piece = EMPTY;
move->check_status = NOCHECK;
move->epd = NULL;
move->fen_suffix = NULL;
move->zobrist = ~0;
move->evaluation = 0;
move->NAGs = NULL;
move->comment_list = NULL;
move->Variants = NULL;
move->prev = NULL;
move->next = NULL;
return move;
}
/* Work out whatever can be gleaned from move_string of
* the starting and ending points of the given move.
* The move may be any legal string.
* The scanning here is libertarian, so it relies heavily on
* illegal moves having already been filtered out by the process
* of lexical analysis.
*/
Move *
decode_move(const unsigned char *move_string)
{ /* The four components of the co-ordinates when known. */
Rank from_rank = 0, to_rank = 0;
Col from_col = 0, to_col = 0;
MoveClass class;
Boolean Ok = TRUE;
/* Temporary locations until known whether they are from_ or to_. */
Col col = 0;
Rank rank = 0;
/* A pointer to move along the move string. */
const unsigned char *move = move_string;
/* A pointer to the structure containing the details to be returned. */
Move *move_details;
Piece piece_to_move = EMPTY;
/* Make an initial distinction between pawn moves and piece moves. */
if (is_col(*move)) {
/* Pawn move. */
class = PAWN_MOVE;
piece_to_move = PAWN;
col = *move;
move++;
if (is_rank(*move)) {
/* e4, e2e4 */
rank = *move;
move++;
if (is_capture(*move)) {
move++;
}
if (is_col(*move)) {
from_col = col;
from_rank = rank;
to_col = *move;
move++;
if (is_rank(*move)) {
to_rank = *move;
move++;
}
}
else {
to_col = col;
to_rank = rank;
}
}
else {
if (is_capture(*move)) {
/* axb */
move++;
}
if (is_col(*move)) {
/* ab, or bg8 for liberal bishop moves. */
from_col = col;
to_col = *move;
move++;
if (is_rank(*move)) {
to_rank = *move;
move++;
/* Check the sanity of this. */
if ((from_col != 'b') &&
(from_col != (to_col + 1)) && (from_col != (to_col - 1))) {
Ok = FALSE;
}
}
else {
/* Check the sanity of this. */
if ((from_col != (to_col + 1)) && (from_col != (to_col - 1))) {
Ok = FALSE;
}
}
}
else {
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown pawn move %s.\n",
move_string);
Ok = FALSE;
}
}
if (Ok) {
/* Look for promotions. */
if (*move == '=') {
move++;
}
/* djb From v17-27 allow a trailing 'b' as a Bishop promotion. */
if (is_piece(move) != EMPTY || *move == 'b') {
class = PAWN_MOVE_WITH_PROMOTION;
/* @@@ Strictly speaking, if the piece is a RUSSIAN_KING
* then we should skip two chars.
*/
move++;
}
}
}
else if ((piece_to_move = is_piece(move)) != EMPTY) {
class = PIECE_MOVE;
/* Check for a two-character piece. */
if ((RUSSIAN_PIECE_CHECK(*move) == RUSSIAN_KNIGHT_OR_KING) &&
(piece_to_move == KING)) {
move++;
}
move++;
if (is_rank(*move)) {
/* A disambiguating rank.
* R1e1, R1xe3.
*/
from_rank = *move;
move++;
if (is_capture(*move)) {
move++;
}
if (is_col(*move)) {
to_col = *move;
move++;
if (is_rank(*move)) {
to_rank = *move;
move++;
}
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown piece move %s.\n",
move_string);
}
}
else {
if (is_capture(*move)) {
/* Rxe1 */
move++;
if (is_col(*move)) {
to_col = *move;
move++;
if (is_rank(*move)) {
to_rank = *move;
move++;
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile,
"Unknown piece move %s.\n", move_string);
}
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown piece move %s.\n",
move_string);
}
}
else if (is_col(*move)) {
col = *move;
move++;
if (is_capture(*move)) {
move++;
}
if (is_rank(*move)) {
/* Re1, Re1d1, Re1xd1 */
rank = *move;
move++;
if (is_capture(*move)) {
move++;
}
if (is_col(*move)) {
/* Re1d1 */
from_col = col;
from_rank = rank;
to_col = *move;
move++;
if (is_rank(*move)) {
to_rank = *move;
move++;
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile,
"Unknown piece move %s.\n", move_string);
}
}
else {
to_col = col;
to_rank = rank;
}
}
else if (is_col(*move)) {
/* Rae1 */
from_col = col;
to_col = *move;
move++;
if (is_rank(*move)) {
to_rank = *move;
move++;
}
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown piece move %s.\n",
move_string);
}
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown piece move %s.\n", move_string);
}
}
}
else if (is_castling_character(*move)) {
/* Some form of castling. */
move++;
/* Allow separators to be optional. */
if (*move == '-') {
move++;
}
if (is_castling_character(*move)) {
move++;
if (*move == '-') {
move++;
}
if (is_castling_character(*move)) {
class = QUEENSIDE_CASTLE;
move++;
}
else {
class = KINGSIDE_CASTLE;
}
}
else {
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown castling move %s.\n", move_string);
Ok = FALSE;
}
}
else if (strcmp((char *) move_string, NULL_MOVE_STRING) == 0) {
class = NULL_MOVE;
}
else {
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile, "Unknown move %s.\n", move_string);
Ok = FALSE;
}
if (Ok && class != NULL_MOVE) {
/* Allow trailing checks. */
while (is_check(*move)) {
move++;
}
if (*move == '\0') {
/* Nothing more to check. */
}
else if (((strcmp((const char *) move, "ep") == 0) ||
(strcmp((const char *) move, "e.p.") == 0)) &&
(class == PAWN_MOVE)) {
/* These are ok. */
class = ENPASSANT_PAWN_MOVE;
}
else {
Ok = FALSE;
print_error_context(GlobalState.logfile);
fprintf(GlobalState.logfile,
"Unknown text trailing move %s <%s>.\n", move_string, move);
}
}
/* Store all of the details gathered, even if the move is illegal. */
if (!Ok) {
class = UNKNOWN_MOVE;
}
move_details = new_move_structure();
strcpy((char *) move_details->move, (const char *) move_string);
move_details->class = class;
move_details->piece_to_move = piece_to_move;
move_details->from_col = from_col;
move_details->from_rank = from_rank;
move_details->to_col = to_col;
move_details->to_rank = to_rank;
move_details->captured_piece = EMPTY;
move_details->check_status = NOCHECK;
return move_details;
}
Move *
decode_algebraic(Move *move_details, Board *board)
{
int from_r = RankConvert(move_details->from_rank);
int from_c = ColConvert(move_details->from_col);
Piece piece_to_move = EXTRACT_PIECE(board->board[from_r][from_c]);
if (piece_to_move != EMPTY) {
/* Check for the special case of castling. */
if ((piece_to_move == KING) && (move_details->from_col == 'e')) {
if (move_details->to_col == 'g') {
move_details->class = KINGSIDE_CASTLE;
}
else if (move_details->to_col == 'c') {
move_details->class = QUEENSIDE_CASTLE;
}
else {
move_details->class = PIECE_MOVE;
move_details->piece_to_move = piece_to_move;
}
}
else {
if (piece_to_move == PAWN) {
move_details->class = PAWN_MOVE;
}
else {
move_details->class = PIECE_MOVE;
}
move_details->piece_to_move = piece_to_move;
}
move_details->captured_piece = EMPTY;
move_details->check_status = NOCHECK;
}
return move_details;
}
/* See if move_string seems to represent the text of a valid move.
* Don't print any error messages, just return TRUE or FALSE.
*/
Boolean
move_seems_valid(const unsigned char *move_string)
{
MoveClass class;
Boolean Ok = TRUE;
/* A pointer to move along the move string. */
unsigned const char *move = move_string;
/* Make an initial distinction between pawn moves and piece moves. */
if (is_col(*move)) {
/* Pawn move. */
class = PAWN_MOVE;
move++;
if (is_rank(*move)) {
/* e4, e2e4 */
move++;
if (is_capture(*move)) {
move++;
}
if (is_col(*move)) {
move++;
if (is_rank(*move)) {
move++;
}
}
else {
}
}
else {
if (is_capture(*move)) {
/* axb */
move++;
}
if (is_col(*move)) {
/* ab */
move++;
if (is_rank(*move)) {
move++;
}
}
else {
Ok = FALSE;
}
}
if (Ok) {
/* Look for promotions. */
if (*move == '=') {
move++;
}
/* djb From v17-27 allow a trailing 'b' as a Bishop promotion. */
if (is_piece(move) != EMPTY || *move == 'b') {
class = PAWN_MOVE_WITH_PROMOTION;
/* @@@ Strictly speaking, if the piece is a RUSSIAN_KING
* then we should skip two chars.
*/
move++;
}
}
}
else if (is_piece(move) != EMPTY) {
class = PIECE_MOVE;
/* Check for a two-character piece. */
if ((RUSSIAN_PIECE_CHECK(*move) == RUSSIAN_KNIGHT_OR_KING) &&
(is_piece(move) == KING)) {
move++;
}
move++;
if (is_rank(*move)) {
/* A disambiguating rank.
* R1e1, R1xe3.
*/
move++;
if (is_capture(*move)) {
move++;
}
if (is_col(*move)) {
move++;
if (is_rank(*move)) {
move++;
}
}
else {
Ok = FALSE;
}
}
else {
if (is_capture(*move)) {
/* Rxe1 */
move++;
if (is_col(*move)) {
move++;
if (is_rank(*move)) {
move++;
}
else {
Ok = FALSE;
}
}
else {
Ok = FALSE;
}
}
else if (is_col(*move)) {
move++;
if (is_capture(*move)) {
move++;
}
if (is_rank(*move)) {
/* Re1, Re1d1, Re1xd1 */
move++;
if (is_capture(*move)) {
move++;
}
if (is_col(*move)) {
/* Re1d1 */
move++;
if (is_rank(*move)) {
move++;
}
else {
Ok = FALSE;
}
}
}
else if (is_col(*move)) {
/* Rae1 */
move++;
if (is_rank(*move)) {
move++;
}
else {
Ok = FALSE;
}
}
else {
Ok = FALSE;
}
}
else {
Ok = FALSE;
}
}
}
else if (is_castling_character(*move)) {
/* Some form of castling. */
move++;
/* Allow separators to be optional. */
if (*move == '-') {
move++;
}
if (is_castling_character(*move)) {
move++;
if (*move == '-') {
move++;
}
if (is_castling_character(*move)) {
class = QUEENSIDE_CASTLE;
move++;
}
else {
class = KINGSIDE_CASTLE;
}
}
else {
Ok = FALSE;
}
}
else {
Ok = FALSE;
}
if (Ok) {
/* Allow trailing checks. */
while (is_check(*move)) {
move++;
}
if (*move == '\0') {
/* Nothing more to check. */
}
else if (((strcmp((const char *) move, "ep") == 0) ||
(strcmp((const char *) move, "e.p.") == 0)) &&
(class == PAWN_MOVE)) {
/* These are ok. */
class = ENPASSANT_PAWN_MOVE;
}
else {
Ok = FALSE;
}
}
return Ok;
}

35
pgn-extract/decode.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef DECODE_H
#define DECODE_H
Move *new_move_structure(void);
Piece is_piece(const unsigned char *move);
Move *decode_move(const unsigned char *move_string);
Move *decode_algebraic(Move *move_details, Board *board);
Boolean is_check(char c);
Boolean is_col(char c);
Boolean is_rank(char c);
Boolean move_seems_valid(const unsigned char *move_string);
#endif // DECODE_H

152
pgn-extract/defs.h Normal file
View File

@@ -0,0 +1,152 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* These colour values are used as modifiers of the Piece values to
* produce pieces of the appropriate colours.
* A coloured piece is formed by shifting the piece value and setting the
* bottom bit to either 0 (BLACK) or 1 (WHITE).
*/
#ifndef DEFS_H
#define DEFS_H
#include <stdint.h>
typedef enum { BLACK, WHITE } Colour;
typedef enum {
OFF, EMPTY,
/* The order of these is important and used in several places.
* In particular, several for-loops iterate from PAWN to KING.
*/
PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
/* Must be last. */
NUM_PIECE_VALUES
} Piece;
/* Different classes of move determined by the lexical analyser. */
typedef enum { PAWN_MOVE, PAWN_MOVE_WITH_PROMOTION, ENPASSANT_PAWN_MOVE,
PIECE_MOVE, KINGSIDE_CASTLE, QUEENSIDE_CASTLE,
NULL_MOVE,
UNKNOWN_MOVE
} MoveClass;
/* Whether who is to move matters for positional matches. */
typedef enum { WHITE_TO_MOVE, BLACK_TO_MOVE, EITHER_TO_MOVE } WhoseMove;
/* Types for algebraic rank and column. */
typedef char Rank;
typedef char Col;
/* Define the base characters for ranks and columns. */
#define RANKBASE '1'
#define COLBASE 'a'
#define FIRSTRANK (RANKBASE)
#define LASTRANK (RANKBASE+BOARDSIZE-1)
#define FIRSTCOL (COLBASE)
#define LASTCOL (COLBASE+BOARDSIZE-1)
/* Convert the given rank to the correct index into a board. */
#define RankConvert(rank) ((FIRSTRANK <= (rank)) && ((rank) <= LASTRANK)?\
((rank)-RANKBASE+HEDGE):0)
/* Convert the given column to the correct index into a board. */
#define ColConvert(col) ((FIRSTCOL <= (col)) && ((col) <= LASTCOL)?\
((col)-COLBASE+HEDGE):0)
/* Convert a board index back to Rank or Col form. */
#define ToRank(r) ((r)+RANKBASE-HEDGE)
#define ToCol(c) ((c)+COLBASE-HEDGE)
#define COLOUR_OFFSET(colour) (((colour) == WHITE)? 1 : -1)
#define BOARDSIZE 8
/* Define the size of a hedge around the board.
* This should have a size of 2 to make calculation of Knight moves easier.
*/
#define HEDGE 2
/* Define a type for position hashing.
* The original type for this is unsigned long.
* @@@ At some point, it would be worth moving this to uint64_t to be
* consistent with the polyglot/zobrist hashing function.
*/
typedef uint64_t HashCode;
typedef struct {
Piece board[HEDGE+BOARDSIZE+HEDGE][HEDGE+BOARDSIZE+HEDGE];
/* Who has the next move. */
Colour to_move;
/* The current move number. */
unsigned move_number;
/* Rook starting columns for the 4 castling options.
* This accommodates Chess960.
*/
Col WKingCastle, WQueenCastle;
Col BKingCastle, BQueenCastle;
/* Keep track of where the two kings are, to make check-detection
* simple.
*/
Col WKingCol; Rank WKingRank;
Col BKingCol; Rank BKingRank;
/* Is EnPassant capture possible? If so then ep_rank and ep_col have
* the square on which this can be made.
*/
Boolean EnPassant;
Rank ep_rank;
Col ep_col;
/* NB: @@@
* This value is based on a relatively weak hashing approach
* that really needs updating to properly use the Zobrist hash.
*/
HashCode weak_hash_value;
/* Provision for storing a Zobrist hash value. However,
* this is only set if GlobalState.add_hashcode_comments.
* At some point, it should supersede the weak_hash_value.
*/
uint64_t zobrist;
/* The half-move clock since the last pawn move or capture. */
unsigned halfmove_clock;
} Board;
/* Define a type that can be used to create a list of possible source
* squares for a move.
*/
typedef struct move_pair {
Col from_col;
Rank from_rank;
Col to_col;
Rank to_rank;
struct move_pair *next;
} MovePair;
/* Conversion macros. */
#define PIECE_SHIFT 3
#define MAKE_COLOURED_PIECE(colour,piece) ((Piece) (((piece) << PIECE_SHIFT) | (colour)))
#define W(piece) MAKE_COLOURED_PIECE(WHITE,piece)
#define B(piece) MAKE_COLOURED_PIECE(BLACK,piece)
/* Conversion macro, from one colour to another. */
#define OPPOSITE_COLOUR(colour) (!(colour))
#define EXTRACT_COLOUR(coloured_piece) ((coloured_piece) & 0x01)
#define EXTRACT_PIECE(coloured_piece) ((coloured_piece) >> PIECE_SHIFT)
/* The string for internally representing the non-standard PGN
* notation for null moves.
*/
#define NULL_MOVE_STRING ("--")
#endif // DEFS_H

332
pgn-extract/eco.c Normal file
View File

@@ -0,0 +1,332 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "map.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
#include "eco.h"
#include "apply.h"
/* Place a limit on how distant a position may be from the ECO line
* it purports to match. This is to try to stop collisions way past
* where the line could still be active.
*/
#define ECO_HALF_MOVE_LIMIT 6
/* Keep track of the longest ECO line, in half moves, plus
* ECO_HALF_MOVE_LIMIT.
* If a line exceeds this length, don't bother attempting
* a match.
*/
static unsigned maximum_half_moves = ECO_HALF_MOVE_LIMIT;
/* Define a table to hold hash values of the ECO positions.
* This is used to enable duplicate detection.
*/
#define ECO_TABLE_SIZE 4096
static EcoLog **EcoTable;
#if INCLUDE_UNUSED_FUNCTIONS
static void
dumpEcoTable(void)
{
unsigned ix;
for (ix = 0; ix < ECO_TABLE_SIZE; ix++) {
if (EcoTable[ix] != NULL) {
EcoLog *entry = NULL;
for (entry = EcoTable[ix]; entry != NULL; entry = entry->next) {
fprintf(stderr, "%s %lu %lu ", entry->ECO_tag,
entry->required_hash_value,
entry->cumulative_hash_value);
}
fprintf(stderr, "\n");
}
}
}
/* Return at how many points this match works.
*
* This is a heuristic attempt to permit later
* longer matches to be chosen in preference to
* earlier shorter matches, while avoiding the
* greater probability of false matches when there
* are a lot of ECO lines and we are further into
* a game.
*/
static int
eco_match_level(EcoLog *entry, HashCode current_hash_value,
HashCode cumulative_hash_value, unsigned half_moves_played)
{
int level = 0;
if (entry != NULL) {
if (entry->required_hash_value == current_hash_value) {
level++;
if (entry->cumulative_hash_value == cumulative_hash_value) {
level++;
if (entry->half_moves == half_moves_played) {
level++;
}
}
}
}
return level;
}
/* Quality values for aspects of an ECO match.
* Currently unused.
*/
static int ECO_REQUIRED_HASH_VALUE = 1;
static int ECO_HALF_MOVE_VALUE = 1;
static int ECO_CUMULATIVE_HASH_VALUE = 0;
/* Rate the quality of the given match.
* Currently unused.
*/
static int eco_match_quality(EcoLog* entry,
HashCode current_hash_value,
HashCode cumulative_hash_value,
int half_moves_played)
{
int quality = 0;
if (entry->required_hash_value == current_hash_value) {
quality += ECO_REQUIRED_HASH_VALUE;
if (abs(half_moves_played - entry->half_moves) <= ECO_HALF_MOVE_LIMIT) {
quality += ECO_HALF_MOVE_VALUE;
}
if (entry->cumulative_hash_value == cumulative_hash_value) {
quality += ECO_CUMULATIVE_HASH_VALUE;
}
}
return quality;
}
#endif
void initEcoTable(void)
{
/* Avoid multiple calls. */
if (EcoTable == NULL) {
int i;
EcoTable = (EcoLog **) malloc_or_die(ECO_TABLE_SIZE * sizeof (EcoLog *));
for (i = 0; i < ECO_TABLE_SIZE; i++) {
EcoTable[i] = NULL;
}
}
}
/* Enter the ECO details of game into EcoTable.
*/
void
save_eco_details(const Game *game_details, const Board *final_position, unsigned number_of_half_moves)
{
unsigned ix = game_details->final_hash_value % ECO_TABLE_SIZE;
EcoLog *entry = NULL;
/* Assume that it can be saved: that there is no collision. */
Boolean can_save = TRUE;
/* In an effort to save string space, keep a record of the
* last entry stored, because there is a good chance that it
* will have the same ECO_tag and Opening_tag as the next
* one.
*/
static EcoLog *last_entry = NULL;
for (entry = EcoTable[ix]; (entry != NULL) && can_save; entry = entry->next) {
if ((entry->required_hash_value == game_details->final_hash_value) &&
(entry->half_moves == number_of_half_moves) &&
(entry->cumulative_hash_value == game_details->cumulative_hash_value)) {
const char *tag = entry->ECO_tag,
*opening = entry->Opening_tag,
*variation = entry->Variation_tag;
if (tag == NULL) {
tag = "";
}
if (opening == NULL) {
opening = "";
}
if (variation == NULL) {
variation = "";
}
fprintf(GlobalState.logfile, "ECO hash collision of ");
fprintf(GlobalState.logfile, "%s %s %s", tag, opening, variation);
fprintf(GlobalState.logfile, " against ");
tag = game_details->tags[ECO_TAG];
opening = game_details->tags[OPENING_TAG];
variation = game_details->tags[VARIATION_TAG];
if (tag == NULL) {
tag = "";
}
if (opening == NULL) {
opening = "";
}
if (variation == NULL) {
variation = "";
}
fprintf(GlobalState.logfile, "%s %s %s\n", tag, opening, variation);
fprintf(GlobalState.logfile, "Possible duplicate move sequences.\n");
can_save = FALSE;
}
}
if (can_save) {
/* First occurrence, so add it to the log. */
entry = (EcoLog *) malloc_or_die(sizeof (*entry));
entry->required_hash_value = game_details->final_hash_value;
entry->cumulative_hash_value = game_details->cumulative_hash_value;
/* Keep a record of the current move number as a sanity
* check on matches.
*/
entry->half_moves = number_of_half_moves;
/* Check for a new greater depth. */
if (number_of_half_moves + ECO_HALF_MOVE_LIMIT > maximum_half_moves) {
maximum_half_moves = number_of_half_moves + ECO_HALF_MOVE_LIMIT;
}
if (game_details->tags[ECO_TAG] != NULL) {
if ((last_entry != NULL) && (last_entry->ECO_tag != NULL) &&
(strcmp(last_entry->ECO_tag, game_details->tags[ECO_TAG]) == 0)) {
/* Share the last entry's tag. */
entry->ECO_tag = last_entry->ECO_tag;
}
else {
entry->ECO_tag = copy_string(game_details->tags[ECO_TAG]);
}
}
else {
entry->ECO_tag = NULL;
}
if (game_details->tags[OPENING_TAG] != NULL) {
if ((last_entry != NULL) && (last_entry->Opening_tag != NULL) &&
(strcmp(last_entry->Opening_tag,
game_details->tags[OPENING_TAG]) == 0)) {
/* Share the last entry's tag. */
entry->Opening_tag = last_entry->Opening_tag;
}
else {
entry->Opening_tag = copy_string(game_details->tags[OPENING_TAG]);
}
}
else {
entry->Opening_tag = NULL;
}
if (game_details->tags[VARIATION_TAG] != NULL) {
entry->Variation_tag = copy_string(game_details->tags[VARIATION_TAG]);
}
else {
entry->Variation_tag = NULL;
}
if (game_details->tags[SUB_VARIATION_TAG] != NULL) {
entry->Sub_Variation_tag =
copy_string(game_details->tags[SUB_VARIATION_TAG]);
}
else {
entry->Sub_Variation_tag = NULL;
}
/* Link it into the head at this index. */
entry->next = EcoTable[ix];
EcoTable[ix] = entry;
/* Keep this one for next time around. */
last_entry = entry;
}
}
/* Look in EcoTable for current_hash_value.
* Use cumulative_hash_value to refine the match.
* An exact match is preferable to a partial match.
*/
EcoLog *
eco_matches(const Board *board, HashCode cumulative_hash_value,
unsigned half_moves_played)
{
HashCode current_hash_value = board->weak_hash_value;
EcoLog *possible = NULL;
/* Don't bother trying if we are too far on in the game. */
if (half_moves_played <= maximum_half_moves) {
/* Where to look. */
unsigned ix = current_hash_value % ECO_TABLE_SIZE;
EcoLog *entry;
for (entry = EcoTable[ix]; entry != NULL; entry = entry->next) {
if (entry->required_hash_value == current_hash_value) {
/* See if we have a full match. */
if (half_moves_played == entry->half_moves &&
entry->cumulative_hash_value == cumulative_hash_value) {
return entry;
}
else if ((half_moves_played - entry->half_moves) <=
ECO_HALF_MOVE_LIMIT) {
/* Retain this as a possible. */
possible = entry;
}
else {
/* Ignore it, as the lines are too distant. */
}
}
}
}
return possible;
}
/* Depending upon the ECO_level and the eco string of the
* current game, open the correctly named ECO file.
*/
FILE *
open_eco_output_file(EcoDivision ECO_level, const char *eco)
{ /* Allow space for the maximum number of
* ECO digits plus a .pgn suffix.
*/
static const char suffix[] = ".pgn";
enum {
MAXNAME = MAX_ECO_LEVEL + sizeof (suffix) - 1
};
static char filename[MAXNAME + 1];
if ((eco == NULL) || !isalpha((int) *eco)) {
strcpy(filename, "noeco.pgn");
}
else if (ECO_level == DONT_DIVIDE) {
fprintf(GlobalState.logfile,
"Internal error: ECO division in open_eco_output_file\n");
strcpy(filename, "noeco");
}
else if (ECO_level == DONT_DIVIDE) {
fprintf(GlobalState.logfile,
"Internal error: ECO division in open_eco_output_file\n");
strcpy(filename, "noeco");
}
else {
strncpy(filename, eco, ECO_level);
filename[ECO_level] = '\0';
strcat(filename, suffix);
}
return must_open_file(filename, "a");
}

51
pgn-extract/eco.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Define a type to hold hash values of interest. */
#ifndef ECO_H
#define ECO_H
typedef struct EcoLog {
HashCode required_hash_value;
/* cumulative_hash_value is used to disambiguate clashing
* final hash values in duplicate detection.
*/
HashCode cumulative_hash_value;
/* How deep the line is, from the half_moves associated with
* the board when the line is played out.
*/
unsigned half_moves;
const char *ECO_tag;
const char *Opening_tag;
const char *Variation_tag;
const char *Sub_Variation_tag;
struct EcoLog *next;
} EcoLog;
EcoLog *eco_matches(const Board *board, HashCode cumulative_hash_value,
unsigned half_moves_played);
Boolean add_ECO(Game game_details);
FILE *open_eco_output_file(EcoDivision ECO_level,const char *eco);
void initEcoTable(void);
void save_eco_details(const Game *game_details, const Board *final_position, unsigned number_of_moves);
#endif // ECO_H

12143
pgn-extract/eco.pgn Normal file

File diff suppressed because it is too large Load Diff

758
pgn-extract/end.c Normal file
View File

@@ -0,0 +1,758 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "end.h"
#include "lines.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
#include "apply.h"
#include "grammar.h"
/**
* Code to handle specifications describing the state of the board
* in terms of numbers of pieces and material balance between opponents.
*
* Games are then matched against these specifications.
*/
/* Keep a list of endings to be found. */
static Material_details *endings_to_match = NULL;
/* What kind of piece is the character, c, likely to represent?
* NB: This is NOT the same as is_piece() in decode.c
*/
/* Define pseudo-letter for minor pieces, used later. */
#define MINOR_PIECE 'L'
static Piece
is_English_piece(char c)
{
Piece piece = EMPTY;
switch (c) {
case 'K': case 'k':
piece = KING;
break;
case 'Q': case 'q':
piece = QUEEN;
break;
case 'R': case 'r':
piece = ROOK;
break;
case 'N': case 'n':
piece = KNIGHT;
break;
case 'B': case 'b':
piece = BISHOP;
break;
case 'P': case 'p':
piece = PAWN;
break;
}
return piece;
}
/* Initialise the count of required pieces prior to reading
* in the data.
*/
static Material_details *
new_ending_details(Boolean both_colours)
{
Material_details *details = (Material_details *) malloc_or_die(sizeof (Material_details));
int c;
Piece piece;
details->both_colours = both_colours;
for (piece = PAWN; piece <= KING; piece++) {
for (c = 0; c < 2; c++) {
details->num_pieces[c][piece] = 0;
details->occurs[c][piece] = EXACTLY;
}
}
/* Fill out some miscellaneous colour based information. */
for (c = 0; c < 2; c++) {
/* Only the KING is a requirement for each side. */
details->num_pieces[c][KING] = 1;
details->match_depth[c] = 0;
/* How many general minor pieces to match. */
details->num_minor_pieces[c] = 0;
details->minor_occurs[c] = EXACTLY;
}
/* Assume that the match must always have a depth of at least two for
* two half-move stability.
*/
details->move_depth = 2;
details->next = NULL;
return details;
}
static const char *
extract_combination(const char *p, Occurs *p_occurs, int *p_number, const char *line)
{
Boolean Ok = TRUE;
Occurs occurs = EXACTLY;
int number = 1;
if (isdigit((int) *p)) {
/* Only single digits are allowed. */
number = *p - '0';
p++;
if (isdigit((int) *p)) {
fprintf(GlobalState.logfile, "Number > 9 is too big in %s.\n",
line);
while (isdigit((int) *p)) {
p++;
}
Ok = FALSE;
}
}
if (Ok) {
/* Look for trailing annotations. */
switch (*p) {
case '*':
number = 0;
occurs = NUM_OR_MORE;
p++;
break;
case '+':
occurs = NUM_OR_MORE;
p++;
break;
case '-':
occurs = NUM_OR_LESS;
p++;
break;
case '?':
number = 1;
occurs = NUM_OR_LESS;
p++;
break;
case '=':
case '#':
case '<':
case '>':
switch (*p) {
case '=':
p++;
occurs = SAME_AS_OPPONENT;
break;
case '#':
p++;
occurs = NOT_SAME_AS_OPPONENT;
break;
case '<':
p++;
if (*p == '=') {
occurs = LESS_EQ_THAN_OPPONENT;
p++;
}
else {
occurs = LESS_THAN_OPPONENT;
}
break;
case '>':
p++;
if (*p == '=') {
occurs = MORE_EQ_THAN_OPPONENT;
p++;
}
else {
occurs = MORE_THAN_OPPONENT;
}
break;
}
break;
}
}
if (Ok) {
*p_occurs = occurs;
*p_number = number;
return p;
}
else {
return NULL;
}
}
/* Extract a single piece set of information from line.
* Return where we have got to as the result.
* colour == WHITE means we are looking at the first set of
* pieces, so some of the notation is illegal (i.e. the relative ops).
*
* The basic syntax for a piece description is:
* piece [number] [occurs]
* For instance:
* P2+ Pawn occurs at least twice or more.
* R= Rook occurs same number of times as opponent. (colour == BLACK)
* P1>= Exactly one pawn more than the opponent. (colour == BLACK)
*/
static const char *
extract_piece_information(const char *line, Material_details *details, Colour colour)
{
const char *p = line;
Boolean Ok = TRUE;
while (Ok && (*p != '\0') && !isspace((int) *p) && *p != MATERIAL_CONSTRAINT) {
Piece piece = is_English_piece(*p);
/* By default a piece should occur exactly once. */
Occurs occurs = EXACTLY;
int number = 1;
if (piece != EMPTY) {
/* Skip over the piece. */
p++;
p = extract_combination(p, &occurs, &number, line);
if (p != NULL) {
if ((piece == KING) && (number != 1)) {
fprintf(GlobalState.logfile, "A king must occur exactly once.\n");
number = 1;
}
else if ((piece == PAWN) && (number > 8)) {
fprintf(GlobalState.logfile,
"No more than 8 pawns are allowed.\n");
number = 8;
}
details->num_pieces[colour][piece] = number;
details->occurs[colour][piece] = occurs;
}
else {
Ok = FALSE;
}
}
else if (isalpha((int) *p) && (toupper((int) *p) == MINOR_PIECE)) {
p++;
p = extract_combination(p, &occurs, &number, line);
if (p != NULL) {
details->num_minor_pieces[colour] = number;
details->minor_occurs[colour] = occurs;
}
else {
Ok = FALSE;
}
}
else {
fprintf(GlobalState.logfile, "Unknown symbol at %s\n", p);
Ok = FALSE;
}
}
if (Ok) {
/* Make a sanity check on the use of minor pieces. */
if ((details->num_minor_pieces[colour] > 0) ||
(details->minor_occurs[colour] != EXACTLY)) {
/* Warn about use of BISHOP and KNIGHT letters. */
if ((details->num_pieces[colour][BISHOP] > 0) ||
(details->occurs[colour][BISHOP] != EXACTLY) ||
(details->num_pieces[colour][KNIGHT] > 0) ||
(details->occurs[colour][KNIGHT] != EXACTLY)) {
fprintf(GlobalState.logfile,
"Warning: the mixture of minor pieces in %s is not guaranteed to work.\n",
line);
fprintf(GlobalState.logfile,
"In a single set it is advisable to stick to either L or B and/or N.\n");
}
}
return p;
}
else {
return NULL;
}
}
/* Extract the piece specification from line and fill out
* details with the pattern information.
*/
static Boolean
decompose_line(const char *line, Material_details *details)
{
const char *p = line;
Boolean Ok = TRUE;
/* Skip initial space. */
while (isspace((int) *p)) {
p++;
}
/* Look for a move depth. */
if (isdigit((int) *p)) {
unsigned depth;
depth = *p - '0';
p++;
while (isdigit((int) *p)) {
depth = (depth * 10)+(*p - '0');
p++;
}
while (isspace((int) *p)) {
p++;
}
details->move_depth = depth;
}
/* Extract two pairs of piece information.
* NB: If the first set of pieces consists of a lone king then that must
* be included explicitly. If the second set consists of a lone
* king then that can be omitted.
*/
p = extract_piece_information(p, details, WHITE);
if (p != NULL) {
while ((*p != '\0') && (isspace((int) *p) || (*p == MATERIAL_CONSTRAINT))) {
p++;
}
if (*p != '\0') {
p = extract_piece_information(p, details, BLACK);
}
else {
/* No explicit requirements for the other colour. */
Piece piece;
for (piece = PAWN; piece <= KING; piece++) {
details->num_pieces[BLACK][piece] = 0;
details->occurs[BLACK][piece] = EXACTLY;
}
details->num_pieces[BLACK][KING] = 1;
details->occurs[BLACK][KING] = EXACTLY;
}
}
if (p != NULL) {
/* Allow trailing text as a comment. */
}
else {
Ok = FALSE;
}
return Ok;
}
/* A new game to be looked for. Indicate that we have not
* started matching any yet.
*/
static void
reset_match_depths(Material_details *endings)
{
for (; endings != NULL; endings = endings->next) {
endings->match_depth[WHITE] = 0;
endings->match_depth[BLACK] = 0;
}
}
/* Try to find a match for the given number of piece details. */
static Boolean
piece_match(int num_available, int num_to_find, int num_opponents, Occurs occurs)
{
Boolean match = FALSE;
switch (occurs) {
case EXACTLY:
match = num_available == num_to_find;
break;
case NUM_OR_MORE:
match = num_available >= num_to_find;
break;
case NUM_OR_LESS:
match = num_available <= num_to_find;
break;
case SAME_AS_OPPONENT:
match = num_available == num_opponents;
break;
case NOT_SAME_AS_OPPONENT:
match = num_available != num_opponents;
break;
case LESS_THAN_OPPONENT:
match = (num_available + num_to_find) <= num_opponents;
break;
case MORE_THAN_OPPONENT:
match = (num_available - num_to_find) >= num_opponents;
break;
case LESS_EQ_THAN_OPPONENT:
/* This means exactly num_to_find less than the
* opponent.
*/
match = (num_available + num_to_find) == num_opponents;
break;
case MORE_EQ_THAN_OPPONENT:
/* This means exactly num_to_find greater than the
* opponent.
*/
match = (num_available - num_to_find) == num_opponents;
break;
default:
fprintf(GlobalState.logfile,
"Inconsistent state %d in piece_match.\n", occurs);
match = FALSE;
}
return match;
}
/* Try to find a match against one player's pieces in the piece_set_colour
* set of details_to_find.
*/
static Boolean
piece_set_match(const Material_details *details_to_find,
int num_pieces[2][NUM_PIECE_VALUES],
Colour game_colour, Colour piece_set_colour)
{
Boolean match = TRUE;
Piece piece;
/* Determine whether we failed on a match for minor pieces or not. */
Boolean minor_failure = FALSE;
/* No need to check KING. */
for (piece = PAWN; (piece < KING) && match; piece++) {
int num_available = num_pieces[game_colour][piece];
int num_opponents = num_pieces[OPPOSITE_COLOUR(game_colour)][piece];
int num_to_find = details_to_find->num_pieces[piece_set_colour][piece];
Occurs occurs = details_to_find->occurs[piece_set_colour][piece];
match = piece_match(num_available, num_to_find, num_opponents, occurs);
if (!match) {
if ((piece == KNIGHT) || (piece == BISHOP)) {
minor_failure = TRUE;
/* Carry on trying to match. */
match = TRUE;
}
else {
minor_failure = FALSE;
}
}
}
if (match) {
/* Ensure that the minor pieces match if there is a minor pieces
* requirement.
*/
int num_to_find = details_to_find->num_minor_pieces[piece_set_colour];
Occurs occurs = details_to_find->minor_occurs[piece_set_colour];
if ((num_to_find > 0) || (occurs != EXACTLY)) {
int num_available =
num_pieces[game_colour][BISHOP] +
num_pieces[game_colour][KNIGHT];
int num_opponents = num_pieces[OPPOSITE_COLOUR(game_colour)][BISHOP] +
num_pieces[OPPOSITE_COLOUR(game_colour)][KNIGHT];
match = piece_match(num_available, num_to_find, num_opponents, occurs);
}
else if (minor_failure) {
/* We actually failed with proper matching of individual minor
* pieces, and no minor match fixup is possible.
*/
match = FALSE;
}
else {
/* Match stands. */
}
}
return match;
}
/* Look for a material match between current_details and
* details_to_find. Only return TRUE if we have both a match
* and match_depth >= move_depth in details_to_find.
* NB: If the game ends before the required depth is reached then a
* potential match would be missed. This could be considered
* as a bug.
*/
static Boolean
material_match(Material_details *details_to_find, int num_pieces[2][NUM_PIECE_VALUES],
Colour game_colour)
{
Boolean match = TRUE;
Colour piece_set_colour = WHITE;
match = piece_set_match(details_to_find, num_pieces, game_colour,
piece_set_colour);
if (match) {
game_colour = OPPOSITE_COLOUR(game_colour);
piece_set_colour = OPPOSITE_COLOUR(piece_set_colour);
match = piece_set_match(details_to_find, num_pieces, game_colour,
piece_set_colour);
/* Reset colour to its original value. */
game_colour = OPPOSITE_COLOUR(game_colour);
}
if (match) {
if (details_to_find->match_depth[game_colour] < details_to_find->move_depth) {
/* Not a full match yet. */
match = FALSE;
details_to_find->match_depth[game_colour]++;
}
else {
/* A stable match. */
}
}
else {
/* Reset the match counter. */
details_to_find->match_depth[game_colour] = 0;
}
return match;
}
/* Extract the numbers of each type of piece from the given board. */
static void extract_pieces_from_board(int num_pieces[2][NUM_PIECE_VALUES], const Board *board)
{
/* Set up num_pieces from the board. */
for(int c = 0; c < 2; c++) {
for(int p = 0; p < NUM_PIECE_VALUES; p++) {
num_pieces[c][p] = 0;
}
}
for(char rank = FIRSTRANK; rank <= LASTRANK; rank++) {
for(char col = FIRSTCOL; col <= LASTCOL; col++) {
int r = RankConvert(rank);
int c = ColConvert(col);
Piece coloured_piece = board->board[r][c];
if(coloured_piece != EMPTY) {
int p = EXTRACT_PIECE(coloured_piece);
num_pieces[EXTRACT_COLOUR(coloured_piece)][p]++;
}
}
}
}
/* Check to see whether the given moves lead to a position
* that matches the given 'ending' position.
* In other words, a position with the required balance
* of pieces.
*/
static Boolean
look_for_material_match(Game *game_details)
{
Boolean game_ok = TRUE;
Boolean match_comment_added = FALSE;
Move *next_move = game_details->moves;
Move *move_for_comment = NULL;
Colour colour = WHITE;
/* The initial game position has the full set of piece details. */
int num_pieces[2][NUM_PIECE_VALUES] = {
/* Dummies for OFF and EMPTY at the start. */
/* P N B R Q K */
{0, 0, 8, 2, 2, 2, 1, 1},
{0, 0, 8, 2, 2, 2, 1, 1}
};
Board *board = new_game_board(game_details->tags[FEN_TAG]);
if(game_details->tags[FEN_TAG] != NULL) {
extract_pieces_from_board(num_pieces, board);
}
/* Ensure that all previous match indications are cleared. */
reset_match_depths(endings_to_match);
/* Keep going while the game is ok, and we have some more
* moves and we haven't exceeded the search depth without finding
* a match.
*/
Boolean matches = FALSE;
Boolean end_of_game = FALSE;
Boolean white_matches = FALSE, black_matches = FALSE;
while (game_ok && !matches && !end_of_game) {
for (Material_details *details_to_find = endings_to_match; !matches && (details_to_find != NULL);
details_to_find = details_to_find->next) {
/* Try before applying each move.
* Note, that we wish to try both ways around because we might
* have WT,BT WF,BT ... If we don't try BLACK on WHITE success
* then we might miss a match because a full match takes several
* separate individual match steps.
*/
white_matches = material_match(details_to_find, num_pieces, WHITE);
if(details_to_find->both_colours) {
black_matches = material_match(details_to_find, num_pieces, BLACK);
}
else {
black_matches = FALSE;
}
if (white_matches || black_matches) {
matches = TRUE;
/* See whether a matching comment is required. */
if (GlobalState.add_position_match_comments && !match_comment_added) {
CommentList *match_comment = create_match_comment(board);
if (move_for_comment != NULL) {
append_comments_to_move(move_for_comment, match_comment);
}
else {
if(game_details->prefix_comment == NULL) {
game_details->prefix_comment = match_comment;
}
else {
CommentList *comm = game_details->prefix_comment;
while(comm->next != NULL) {
comm = comm->next;
}
comm->next = match_comment;
}
}
}
}
}
if(matches) {
/* Nothing required. */
}
else if(next_move == NULL) {
end_of_game = TRUE;
}
else if (*(next_move->move) != '\0') {
/* Try the next position. */
if (apply_move(next_move, board)) {
/* Remove any captured pieces. */
if (next_move->captured_piece != EMPTY) {
num_pieces[OPPOSITE_COLOUR(colour)][next_move->captured_piece]--;
}
if (next_move->promoted_piece != EMPTY) {
num_pieces[colour][next_move->promoted_piece]++;
/* Remove the promoting pawn. */
num_pieces[colour][PAWN]--;
}
move_for_comment = next_move;
colour = OPPOSITE_COLOUR(colour);
next_move = next_move->next;
}
else {
game_ok = FALSE;
}
}
else {
/* An empty move. */
fprintf(GlobalState.logfile,
"Internal error: Empty move in look_for_material_match.\n");
game_ok = FALSE;
}
}
(void) free((void *) board);
if(game_ok && matches) {
if(GlobalState.add_match_tag) {
game_details->tags[MATERIAL_MATCH_TAG] =
copy_string(white_matches ? "White" : "Black");
}
return TRUE;
}
else {
return FALSE;
}
}
/* Check to see whether the given moves lead to a position
* that matches one of the required 'material match' positions.
* In other words, a position with the required balance
* of pieces.
*/
Boolean
check_for_material_match(Game *game)
{
/* Match if there are no endings to match. */
if(endings_to_match != NULL) {
return look_for_material_match(game);
}
else {
return TRUE;
}
}
/* Does the board's material match the constraints of details_to_find?
* Return TRUE if it does, FALSE otherwise.
*/
Boolean
constraint_material_match(Material_details *details_to_find, const Board *board)
{
/* Only a single match position is required. */
details_to_find->move_depth = 0;
details_to_find->match_depth[0] = 0;
details_to_find->match_depth[1] = 0;
int num_pieces[2][NUM_PIECE_VALUES];
extract_pieces_from_board(num_pieces, board);
Boolean white_matches = material_match(details_to_find, num_pieces, WHITE);
Boolean black_matches;
if(details_to_find->both_colours) {
black_matches = material_match(details_to_find, num_pieces, BLACK);
}
else {
black_matches = FALSE;
}
return white_matches || black_matches;
}
/* Decompose the text of line to extract two sets of
* piece configurations.
* If both_colours is TRUE then matches will be tried
* for both colours in each configuration.
* Otherwise, the first set of pieces are assumed to
* be white and the second to be black.
* If pattern_constraint is TRUE then the description
* is a constraint of a FEN pattern and should not be
* retained as a separate material match.
*/
Material_details *
process_material_description(const char *line, Boolean both_colours, Boolean pattern_constraint)
{
Material_details *details = NULL;
if (non_blank_line(line)) {
details = new_ending_details(both_colours);
if (decompose_line(line, details)) {
if(!pattern_constraint) {
/* Add it on to the list. */
details->next = endings_to_match;
endings_to_match = details;
}
}
else {
(void) free((void *) details);
details = NULL;
}
}
return details;
}
/* Read a file containing material matches. */
Boolean
build_endings(const char *infile, Boolean both_colours)
{
FILE *fp = fopen(infile, "r");
Boolean Ok = TRUE;
if (fp == NULL) {
fprintf(GlobalState.logfile, "Cannot open %s for reading.\n", infile);
exit(1);
}
else {
char *line;
while ((line = read_line(fp)) != NULL) {
if(process_material_description(line, both_colours, FALSE) == NULL) {
Ok = FALSE;
}
(void) free(line);
}
(void) fclose(fp);
}
return Ok;
}

70
pgn-extract/end.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef END_H
#define END_H
/* Define a type to represent classes of occurrance. */
typedef enum {
EXACTLY, NUM_OR_MORE, NUM_OR_LESS,
SAME_AS_OPPONENT, NOT_SAME_AS_OPPONENT,
LESS_THAN_OPPONENT, MORE_THAN_OPPONENT,
LESS_EQ_THAN_OPPONENT, MORE_EQ_THAN_OPPONENT
} Occurs;
/* Define a structure to hold details on the occurrances of
* each of the pieces.
*/
typedef struct material_details {
/* Whether the pieces are to be tried against
* both colours.
*/
Boolean both_colours;
/* The number of each set of pieces. */
int num_pieces[2][NUM_PIECE_VALUES];
Occurs occurs[2][NUM_PIECE_VALUES];
/* Numbers of general minor pieces. */
int num_minor_pieces[2];
Occurs minor_occurs[2];
/* How long a given relationship must last to be recognised.
* This value is in half moves.
*/
unsigned move_depth;
/* How long a match relationship has been matched.
* This is always reset to zero on failure and incremented on
* success. A full match is only returned when match_depth == move_depth.
*/
unsigned match_depth[2];
struct material_details *next;
} Material_details;
/* Character to separate a pattern from material constraints.
* NB: This is used to add a material constraint to a FEN pattern.
*/
#define MATERIAL_CONSTRAINT ':'
Boolean check_for_material_match(Game *game);
Boolean build_endings(const char *infile, Boolean both_colours);
Material_details *process_material_description(const char *line, Boolean both_colours, Boolean pattern_constraint);
Boolean constraint_material_match(Material_details *details_to_find, const Board *board);
#endif // END_H

632
pgn-extract/fenmatcher.c Normal file
View File

@@ -0,0 +1,632 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "grammar.h"
#include "apply.h"
#include "fenmatcher.h"
#include "end.h"
/* Character on an encoded board representing an empty square. */
#define EMPTY_SQUARE '_'
/* Pattern meta characters. */
#define NON_EMPTY_SQUARE '!'
#define ANY_SQUARE_STATE '?'
#define ZERO_OR_MORE_OF_ANYTHING '*'
#define ANY_WHITE_PIECE 'A'
#define ANY_BLACK_PIECE 'a'
#define NOT_A_PAWN 'm'
/* Symbols for closures. */
#define CCL_START '['
#define CCL_END ']'
#define NCCL '^'
/**
* Based on original pattern matching code by Rob Pike.
* Taken from:
* http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html
* and ideas from Kernighan and Plauger's "Software Tools".
*/
/* A single rank of a FEN-based patterns to match.
* Ranks are chained as a linear list via next_rank and
* alternatives for the same rank via alternative_rank.
* The optional_label (if any) is stored with the final rank of
* the list.
*/
typedef struct FENPatternMatch {
char *rank;
const char *optional_label;
struct FENPatternMatch *alternative_rank;
struct FENPatternMatch *next_rank;
Material_details *constraint;
} FENPatternMatch;
static FENPatternMatch *pattern_tree = NULL;
static Boolean matchhere(const char *regexp, const char *text);
static Boolean matchstar(const char *regexp, const char *text);
static Boolean matchccl(const char *regexp, const char *text);
static Boolean matchnccl(const char *regexp, const char *text);
static Boolean matchone(char regchar, char textchar);
static void convert_rank_to_text(const Board *board, Rank rank, char *text);
static const char *reverse_fen_pattern(const char *pattern);
static void pattern_tree_insert(char **ranks, const char *label, Material_details *constraint);
static void insert_pattern(FENPatternMatch *node, FENPatternMatch *next);
static const char *pattern_match_rank(const Board *board,
FENPatternMatch *pattern, int patternIndex,
char ranks[BOARDSIZE+1][BOARDSIZE+1]);
/*
* Add a FENPattern to be matched. If add_reverse is TRUE then
* additionally add a second pattern that has the colours reversed.
* If label is non-NULL then associate it with fen_pattern for possible
* output in a tag when the pattern is matched.
*/
void
add_fen_pattern(const char *fen_pattern, Boolean add_reverse, const char *label)
{
/* Check the pattern has reasonable syntax. */
/* Count the number of rank dividers. */
int dividers = 0;
/* Count the number of symbols in each rank - must be
* at least one.
*/
int rankSymbols = 0;
Boolean ok = TRUE;
const char *p = fen_pattern;
const char *rank_start = fen_pattern;
Boolean in_closure = FALSE;
char **ranks = (char **) malloc_or_die(BOARDSIZE * sizeof(*ranks));
while (*p != '\0' && *p != ' ' && *p != MATERIAL_CONSTRAINT && ok) {
if (*p == '/') {
/* End of this rank. */
if (rankSymbols == 0) {
/* Nothing on the previous rank. */
ok = FALSE;
}
else {
int num_chars = p - rank_start;
ranks[dividers] = (char *) malloc_or_die(num_chars + 1);
strncpy(ranks[dividers], rank_start, num_chars);
ranks[dividers][num_chars] = '\0';
dividers++;
rank_start = p + 1;
}
rankSymbols = 0;
}
else if (*p == CCL_START) {
if (!in_closure) {
in_closure = TRUE;
}
else {
ok = FALSE;
fprintf(GlobalState.logfile,
"Nested closures not allowed: %s\n",
fen_pattern);
}
}
else if (*p == CCL_END) {
if (in_closure) {
in_closure = FALSE;
}
else {
ok = FALSE;
fprintf(GlobalState.logfile,
"Missing %c to match %c: %s\n",
CCL_START, CCL_END,
fen_pattern);
}
}
else if (*p == NCCL) {
if (!in_closure) {
ok = FALSE;
fprintf(GlobalState.logfile,
"%c not allowed outside %c...%c: %s\n",
NCCL,
CCL_START, CCL_END,
fen_pattern);
}
}
else {
rankSymbols++;
}
p++;
}
if (dividers != BOARDSIZE - 1) {
ok = FALSE;
}
else if (rankSymbols == 0) {
ok = FALSE;
}
else if(ok) {
/* Store the final regexp of the pattern. */
int num_chars = p - rank_start;
ranks[dividers] = (char *) malloc_or_die(num_chars + 1);
strncpy(ranks[dividers], rank_start, num_chars);
ranks[dividers][num_chars] = '\0';
}
if (ok) {
Material_details *constraint;
if(*p == MATERIAL_CONSTRAINT) {
p++;
/* Deal with a constraint on the material that must also match. */
constraint = process_material_description(p, add_reverse, TRUE);
}
else {
constraint = NULL;
}
pattern_tree_insert(ranks, label != NULL ? copy_string(label) : copy_string(""), constraint);
/* Do the same again if a reversed version is required. */
if(add_reverse) {
char *pattern = copy_string(fen_pattern);
/* Terminate at the end of the board position
as we are not interested in the castling rights
or who is to move.
*/
pattern[p - fen_pattern] = '\0';
const char *reversed = reverse_fen_pattern(pattern);
if(label != NULL) {
/* Add a suffix to make it clear that this is
* a match of the inverted form.
*/
char *rlabel = (char *) malloc_or_die(strlen(label) + 1 + 1);
strcpy(rlabel, label);
strcat(rlabel, "I");
add_fen_pattern(reversed, FALSE, rlabel);
}
else {
add_fen_pattern(reversed, FALSE, "");
}
}
}
else {
fprintf(GlobalState.logfile, "FEN Pattern: %s badly formed.\n",
fen_pattern);
}
}
/* Invert the colour sense of the given FENPattern.
* Return the inverted form.
*/
static const char *reverse_fen_pattern(const char *pattern)
{
/* Completely switch the rows and invert the case of each piece letter. */
char **rows = (char **) malloc_or_die(8 * sizeof(*rows));
char *start = copy_string(pattern);
char *end = start;
/* Isolate each row in its new order. */
int row;
for(row = BOARDSIZE - 1; row >= 0 && *start != '\0'; row--) {
/* Find the end of the next row. */
while(*end != '/' && *end != '\0') {
end++;
}
rows[row] = (char *) malloc_or_die((end - start + 1) * sizeof(**rows));
strncpy(rows[row], start, end - start);
rows[row][end - start] = '\0';
start = end;
if(*start != '\0') {
start++;
}
end++;
}
char *reversed = (char *) malloc_or_die(strlen(pattern) + 1);
/* Copy across the rows, flipping the colours. */
char *nextchar = reversed;
for(row = 0; row < 8; row++) {
const char *text = rows[row];
while(*text != '\0') {
if(isalpha(*text)) {
if(islower(*text)) {
*nextchar = toupper(*text);
}
else {
*nextchar = tolower(*text);
}
}
else {
*nextchar = *text;
}
text++;
nextchar++;
}
if(row != BOARDSIZE - 1) {
*nextchar = '/';
nextchar++;
}
}
*nextchar = '\0';
return reversed;
}
/*
* Insert the ranks of a single pattern into the current pattern tree
* to consolidate similar patterns.
*/
static void
pattern_tree_insert(char **ranks, const char *label, Material_details *constraint)
{
FENPatternMatch *match = (FENPatternMatch *) malloc_or_die(sizeof(*match));
/* Create a linked list for the ranks.
* Place the label in the final link.
*/
FENPatternMatch *next = match;
for(int i = 0; i < BOARDSIZE; i++) {
next->rank = ranks[i];
next->alternative_rank = NULL;
if(i != BOARDSIZE - 1) {
next->next_rank = (FENPatternMatch *) malloc_or_die(sizeof(*match));
next->optional_label = NULL;
next->constraint = NULL;
next = next->next_rank;
}
else {
next->next_rank = NULL;
next->optional_label = label;
next->constraint = constraint;
}
}
if(pattern_tree == NULL) {
pattern_tree = match;
}
else {
/* Find the place to insert this list in the existing tree. */
insert_pattern(pattern_tree, match);
}
}
/* Starting at node, try to insert next into the tree.
* Return TRUE on success, FALSE on failure.
*/
static void
insert_pattern(FENPatternMatch *node, FENPatternMatch *next)
{
Boolean inserted = FALSE;
while(!inserted && strcmp(node->rank, next->rank) == 0) {
if(node->next_rank != NULL) {
/* Same pattern. Move to the next rank of both. */
node = node->next_rank;
next = next->next_rank;
}
else {
/* Patterns are duplicates. */
fprintf(GlobalState.logfile, "Warning: duplicate FEN patterns detected.\n");
inserted = TRUE;
}
}
if(!inserted) {
/* Insert as an alternative. */
if(node->alternative_rank != NULL) {
insert_pattern(node->alternative_rank, next);
}
else {
node->alternative_rank = next;
}
}
}
/*
* Try to match the board against one of the FEN patterns.
* Return NULL if no match, otherwise a possible label for the
* match to be added to the game's tags. An empty string is
* used for no label.
*/
const char *
pattern_match_board(const Board *board)
{
const char *match_label = NULL;
if(pattern_tree != NULL) {
/* Don't convert any ranks of the board until they
* are required.
*/
char ranks[BOARDSIZE+1][BOARDSIZE+1];
for(int i = 0; i < BOARDSIZE; i++) {
ranks[i][0] = '\0';
}
match_label = pattern_match_rank(board, pattern_tree, 0, ranks);
}
return match_label;
}
/* Match ranks[patternIndex ...] against board.
* return the corresponding match label if a match is found.
* Return NULL if no match is found.
*/
static const char *pattern_match_rank(const Board *board, FENPatternMatch *pattern, int patternIndex, char ranks[BOARDSIZE+1][BOARDSIZE+1])
{
const char *match_label = NULL;
if(ranks[patternIndex][0] == '\0') {
/* Convert the required rank.
* Convert the others when/if needed.
*/
convert_rank_to_text(board, LASTRANK - patternIndex, ranks[patternIndex]);
}
while(match_label == NULL && pattern != NULL) {
if(matchhere(pattern->rank, ranks[patternIndex])) {
if(patternIndex == BOARDSIZE - 1) {
/* The board matches the pattern. */
if(pattern->constraint != NULL) {
if(constraint_material_match(pattern->constraint, board)) {
match_label = pattern->optional_label;
}
}
else {
match_label = pattern->optional_label;
}
}
else {
/* Try next rank.*/
match_label = pattern_match_rank(board, pattern->next_rank, patternIndex + 1, ranks);
}
}
if(match_label == NULL) {
pattern = pattern->alternative_rank;
}
}
return match_label;
}
/**
* matchhere: search for regexp at beginning of text
*/
static Boolean
matchhere(const char *regexp, const char *text)
{
if (regexp[0] == '\0' && text[0] == '\0') {
return TRUE;
}
if (regexp[0] == ZERO_OR_MORE_OF_ANYTHING) {
return matchstar(regexp + 1, text);
}
if (*text != '\0') {
switch (*regexp) {
case ANY_SQUARE_STATE:
return matchhere(regexp + 1, text + 1);
break;
case NON_EMPTY_SQUARE:
case ANY_WHITE_PIECE:
case ANY_BLACK_PIECE:
case NOT_A_PAWN:
if (matchone(*regexp, *text)) {
return matchhere(regexp + 1, text + 1);
}
break;
case CCL_START:
/* Closure */
if (regexp[1] == NCCL) {
return matchnccl(regexp + 2, text);
}
else {
return matchccl(regexp + 1, text);
}
break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
{
/* The number of empty squares required. */
int empty = regexp[0] - '0';
Boolean matches = TRUE;
/* The number matched. */
int match_count = 0;
while (matches && match_count < empty) {
if (text[match_count] == EMPTY_SQUARE) {
match_count++;
}
else {
matches = FALSE;
}
}
if (matches) {
return matchhere(regexp + 1, text + match_count);
}
}
break;
default:
if (*regexp == *text) {
return matchhere(regexp + 1, text + 1);
}
break;
}
}
/* No match. */
return FALSE;
}
/**
* matchstar: leftmost longest search on a single rank.
*/
static Boolean
matchstar(const char *regexp, const char *text)
{
const char *t;
/* Find the end of this rank. */
for (t = text; *t != '\0'; t++) {
;
}
/* Try from the longest match to the shortest until success. */
do {
/* * matches zero or more */
if (matchhere(regexp, t)) {
return TRUE;
}
} while (t-- > text);
return FALSE;
}
/*
* Return TRUE if regchar matches textchar, FALSE otherwise.
*/
static Boolean
matchone(char regchar, char textchar)
{
if (regchar == textchar) {
return TRUE;
}
else {
switch (regchar) {
case NON_EMPTY_SQUARE:
return textchar != EMPTY_SQUARE;
case ANY_WHITE_PIECE:
/* Match any white piece. */
switch (textchar) {
case 'K':
case 'Q':
case 'R':
case 'N':
case 'B':
case 'P':
return TRUE;
default:
return FALSE;
}
case ANY_BLACK_PIECE:
/* Match any black piece. */
switch (textchar) {
case 'k':
case 'q':
case 'r':
case 'n':
case 'b':
case 'p':
return TRUE;
default:
return FALSE;
}
case ANY_SQUARE_STATE:
return TRUE;
case NOT_A_PAWN:
switch(textchar) {
case 'P':
case 'p':
return FALSE;
default:
return TRUE;
}
default:
return FALSE;
}
}
}
/*
* Match any of the character closure.
*/
static Boolean
matchccl(const char *regexp, const char *text)
{
while (*regexp != CCL_END &&
!matchone(*regexp, *text) && *regexp != '\0') {
regexp++;
}
if (matchone(*regexp, *text)) {
do {
regexp++;
} while (*regexp != CCL_END && *regexp != '\0');
return matchhere(regexp + 1, text + 1);
}
else {
return FALSE;
}
}
/*
* Match any of the characters not in the closure.
*/
static Boolean
matchnccl(const char *regexp, const char *text)
{
while (*regexp != CCL_END &&
!matchone(*regexp, *text) && *regexp != '\0') {
regexp++;
}
if (*regexp == CCL_END) {
return matchhere(regexp + 1, text + 1);
}
else {
return FALSE;
}
}
#if 0
/* Build a basic EPD string from the given board. */
static char *
convert_board_to_text(const Board *board)
{
Rank rank;
int ix = 0;
/* Allow space for a full board and '/' separators in between. */
char *text = (char *) malloc_or_die(8 * 8 + 8);
for (rank = LASTRANK; rank >= FIRSTRANK; rank--) {
const Piece *rankP = board->board[RankConvert(rank)];
Col col;
for (col = FIRSTCOL; col <= LASTCOL; col++) {
int coloured_piece = rankP[ColConvert(col)];
if (coloured_piece != EMPTY) {
text[ix] = coloured_piece_to_SAN_letter(coloured_piece);
}
else {
text[ix] = EMPTY_SQUARE;
}
ix++;
}
if (rank != FIRSTRANK) {
text[ix] = '/';
ix++;
}
}
text[ix] = '\0';
return text;
}
#endif
/* Build a basic EPD string from rank of the given board. */
static void
convert_rank_to_text(const Board *board, Rank rank, char *text)
{
const Piece *rankP = board->board[RankConvert(rank)];
int ix = 0;
Col col;
for (col = FIRSTCOL; col <= LASTCOL; col++) {
int coloured_piece = rankP[ColConvert(col)];
if (coloured_piece != EMPTY) {
text[ix] = coloured_piece_to_SAN_letter(coloured_piece);
}
else {
text[ix] = EMPTY_SQUARE;
}
ix++;
}
text[ix] = '\0';
}

29
pgn-extract/fenmatcher.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef FENMATCHER_H
#define FENMATCHER_H
void add_fen_pattern(const char *fen_pattern, Boolean add_reverse, const char *label);
const char *pattern_match_board(const Board *board);
#endif // FENMATCHER_H

1426
pgn-extract/grammar.c Normal file

File diff suppressed because it is too large Load Diff

36
pgn-extract/grammar.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef GRAMMAR_H
#define GRAMMAR_H
int yyparse(SourceFileType file_type);
void free_string_list(StringList *list);
void init_game_header(void);
void increase_game_header_tags_length(unsigned new_length);
void report_details(FILE *outfp);
void append_comments_to_move(Move *move,CommentList *Comment);
/* The following function is used for linking list items together. */
StringList *save_string_list_item(StringList *list,const char *str);
void free_comment_list(CommentList *comment_list);
#endif // GRAMMAR_H

604
pgn-extract/hashing.c Normal file
View File

@@ -0,0 +1,604 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined(__BORLANDC__) || defined(_MSC_VER)
/* For unlink() */
#include <io.h>
#else
/* For unlink() */
#include <unistd.h>
#endif
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
#include "hashing.h"
#include "zobrist.h"
/* Routines, similar in nature to those in apply.c
* to implement a duplicate hash-table lookup using
* an external file, rather than malloc'd memory.
* The only limit should be a file system limit.
* NB: Using an external, virtual file seems obsolete now.
*
* This version should be slightly more accurate than
* the alternative because the final_ and cumulative_
* hash values are both stored, rather than the XOR
* of them.
*/
/*
* The name of the file used.
* This is overwritten each time, and removed on normal
* program exit.
*/
static char VIRTUAL_FILE[] = "virtual.tmp";
/* Define the size of the hash table.
*/
#define LOG_TABLE_SIZE 100003
/* Define a table to hold hash values of the extracted games.
* This is used to enable duplicate detection.
*/
typedef struct {
/* Record the file offset of the first and last entries
* for an index. (head == -1) => empty.
*/
long head, tail;
} LogHeaderEntry;
/* If use_virtual_hash_table */
static LogHeaderEntry *VirtualLogTable = NULL;
/* Define a table to hold hash values of the extracted games.
* This is used to enable duplicate detection when not using
* the virtual hash table.
*/
static HashLog **LogTable = NULL;
/* Define a type to hold hash values of interest.
* This is used both to aid in duplicate detection
* and in finding positional variations.
*/
typedef struct VirtualHashLog {
/* Store the final position hash value and
* the cumulative hash value for a game.
*/
HashCode final_hash_value, cumulative_hash_value;
/* Record the file list index for the file this game was first found in. */
int file_number;
/* Record the file offset of the next element
* in this list. -1 => end-of-list.
*/
long next;
} VirtualHashLog;
static FILE *hash_file = NULL;
static const char *previous_virtual_occurance(Game game_details);
/*
* Check whether the position counts indicate a desired repetition.
* If we are checking for repetition return TRUE if it does and FALSE otherwise.
* If we are not then return TRUE.
*/
Boolean check_for_only_repetition(PositionCount *position_counts)
{
if (GlobalState.check_for_repetition > 0) {
PositionCount *entry = position_counts;
while (entry != NULL && entry->count < GlobalState.check_for_repetition) {
entry = entry->next;
}
return entry != NULL;
}
else {
return TRUE;
}
}
/*
* Encode the castling rights of the current board
* as a 4-bit pattern.
*/
static unsigned short
encode_castling_rights(const Board *board)
{
unsigned short rights = 0;
if(board->WKingCastle) {
rights |= 0x08;
}
if(board->WQueenCastle) {
rights |= 0x04;
}
if(board->BKingCastle) {
rights |= 0x02;
}
if(board->BQueenCastle) {
rights |= 0x01;
}
return rights;
}
/*
* Return TRUE if the position on board matches the entry details
* for the purposes of position repetition matches:
* + Same board position (based on a hash value)
* + Same castling rights.
* + Same en passant status (i.e., no ep possible).
* + Same player to move.
*/
static Boolean
position_matches(PositionCount *entry, const Board *board)
{
if(board->weak_hash_value != entry->hash_value) {
return FALSE;
}
else if(board->to_move != entry->to_move) {
return FALSE;
}
else if(encode_castling_rights(board) != entry->castling_rights) {
return FALSE;
}
else {
if(board->EnPassant) {
return board->ep_rank == entry->ep_rank && board->ep_col == entry->ep_col;
}
else {
return entry->ep_rank == '\0';
}
}
}
/*
* Add hash_value as a position in the current game.
* Return the number of times this position has occurred.
* NB: The assumption is that position_counts is not NULL.
*/
unsigned
update_position_counts(PositionCount *position_counts, const Board *board)
{
//fprintf(stderr, "U: %d,%d\n", board->ep_rank, board->ep_col);
PositionCount *entry = position_counts;
if (position_counts == NULL) {
/* Don't try to match in variations. */
return 0;
}
/* Try to find an existing entry. */
while (entry != NULL && !position_matches(entry, board)) {
entry = entry->next;
}
if (entry == NULL) {
/* New position. */
entry = new_position_count_list(board);
/* Insert just after the head of the list. */
entry->next = position_counts->next;
position_counts->next = entry;
}
else {
/* Increment the count. */
entry->count++;
}
return entry->count;
}
/*
* Free the list of position counts.
*/
void
free_position_count_list(PositionCount *position_counts)
{
PositionCount *entry = position_counts;
while (entry != NULL) {
PositionCount *next = entry->next;
(void) free((void *) entry);
entry = next;
}
}
/*
* Create a new position count list.
* This will have a single entry at its head.
*/
PositionCount *
new_position_count_list(const Board *board)
{
PositionCount *head = (PositionCount *) malloc_or_die(sizeof (*head));
head->hash_value = board->weak_hash_value;
head->to_move = board->to_move;
head->castling_rights = encode_castling_rights(board);
if(board->EnPassant) {
head->ep_rank = board->ep_rank;
head->ep_col = board->ep_col;
}
else {
head->ep_rank = '\0';
head->ep_col = '\0';
}
head->count = 1;
head->next = NULL;
return head;
}
/*
* Return an identical copy of the given list.
*/
PositionCount *copy_position_count_list(PositionCount *original)
{
PositionCount *copy = NULL;
PositionCount *tail = NULL;
while (original != NULL) {
PositionCount *entry = (PositionCount *) malloc_or_die(sizeof (*entry));
entry->hash_value = original->hash_value;
entry->to_move = original->to_move;
entry->castling_rights = original->castling_rights;
entry->count = original->count;
entry->next = NULL;
if (copy == NULL) {
copy = entry;
}
else {
tail->next = entry;
}
tail = entry;
original = original->next;
}
return copy;
}
/* Determine which table to initialise, depending
* on whether use_virtual_hash_table is set or not.
*/
void
init_duplicate_hash_table(void)
{
int i;
if (GlobalState.use_virtual_hash_table) {
VirtualLogTable = (LogHeaderEntry *)
malloc_or_die(LOG_TABLE_SIZE * sizeof (*VirtualLogTable));
for (i = 0; i < LOG_TABLE_SIZE; i++) {
VirtualLogTable[i].head = VirtualLogTable[i].tail = -1;
}
hash_file = fopen(VIRTUAL_FILE, "w+b");
if (hash_file == NULL) {
fprintf(GlobalState.logfile, "Unable to open %s\n",
VIRTUAL_FILE);
}
}
else {
LogTable = (HashLog**) malloc_or_die(LOG_TABLE_SIZE * sizeof (*LogTable));
for (i = 0; i < LOG_TABLE_SIZE; i++) {
LogTable[i] = NULL;
}
}
}
/* Close and remove the temporary file if in use. */
void
clear_duplicate_hash_table(void)
{
if (GlobalState.use_virtual_hash_table) {
if (hash_file != NULL) {
(void) fclose(hash_file);
unlink(VIRTUAL_FILE);
hash_file = NULL;
}
}
}
/* Retrieve a duplicate table entry from the hash file. */
static int
retrieve_virtual_entry(long ix, VirtualHashLog *entry)
{
if (hash_file == NULL) {
return 0;
}
else if (fseek(hash_file, ix, SEEK_SET) != 0) {
fprintf(GlobalState.logfile,
"Fseek error to %ld in retrieve_virtual_entry\n", ix);
return 0;
}
else if (fread((void *) entry, sizeof (*entry), 1, hash_file) != 1) {
fprintf(GlobalState.logfile,
"Fread error from %ld in retrieve_virtual_entry\n", ix);
return 0;
}
else {
return 1;
}
}
/* Write a duplicate table entry to the hash file. */
static int
write_virtual_entry(long where, const VirtualHashLog *entry)
{
if (fseek(hash_file, where, SEEK_SET) != 0) {
fprintf(GlobalState.logfile,
"Fseek error to %ld in write_virtual_entry\n", where);
return 0;
}
else if (fwrite((void *) entry, sizeof (*entry), 1, hash_file) != 1) {
fprintf(GlobalState.logfile,
"Fwrite error from %ld in write_virtual_entry\n", where);
fflush(hash_file);
return 0;
}
else {
/* Written ok. */
return 1;
}
}
/* Return the name of the original file if it looks like we
* have met the moves in game_details before, otherwise return
* NULL. A match is assumed to be so if both
* the final_ and cumulative_ hash values in game_details
* are already present in VirtualLogTable.
*/
static const char *
previous_virtual_occurance(Game game_details)
{
unsigned ix = game_details.final_hash_value % LOG_TABLE_SIZE;
VirtualHashLog entry;
Boolean duplicate = FALSE;
const char *original_filename = NULL;
/* Are we keeping this information? */
if (GlobalState.suppress_duplicates || GlobalState.suppress_originals ||
GlobalState.duplicate_file != NULL) {
if (VirtualLogTable[ix].head < 0l) {
/* First occurrence. */
}
else {
int keep_going =
retrieve_virtual_entry(VirtualLogTable[ix].head, &entry);
while (keep_going && !duplicate) {
if ((entry.final_hash_value == game_details.final_hash_value) &&
(entry.cumulative_hash_value == game_details.cumulative_hash_value)) {
/* We have a match.
* Determine where it first occured.
*/
original_filename = input_file_name(entry.file_number);
duplicate = TRUE;
}
else if (entry.next >= 0l) {
keep_going = retrieve_virtual_entry(entry.next, &entry);
}
else {
keep_going = 0;
}
}
}
if (!duplicate) {
/* Write an entry for it. */
/* Where to write the next VirtualHashLog entry. */
static long next_free_entry = 0l;
/* Avoid valgrind error when writing unset bytes that
* are part of the structure padding.
*/
memset((void *) &entry, 0, sizeof(entry));
/* Store the XOR of the two hash values. */
entry.final_hash_value = game_details.final_hash_value;
entry.cumulative_hash_value = game_details.cumulative_hash_value;
entry.file_number = current_file_number();
entry.next = -1l;
/* Write out these details. */
if (write_virtual_entry(next_free_entry, &entry)) {
long where_written = next_free_entry;
/* Move on ready for next time. */
next_free_entry += sizeof (entry);
/* Now update the index table. */
if (VirtualLogTable[ix].head < 0l) {
/* First occurrence. */
VirtualLogTable[ix].head =
VirtualLogTable[ix].tail = where_written;
}
else {
VirtualHashLog tail;
if (retrieve_virtual_entry(VirtualLogTable[ix].tail, &tail)) {
tail.next = where_written;
(void) write_virtual_entry(VirtualLogTable[ix].tail, &tail);
/* Store the new tail address. */
VirtualLogTable[ix].tail = where_written;
}
}
}
}
}
return original_filename;
}
/* Return the name of the original file if it looks like we
* have met the moves in game_details before, otherwise return
* NULL.
* For non-fuzzy comparison, a match is assumed to be so if both
* final_ and cumulative_ hash values are already present
* as a pair in LogTable.
* Fuzzy matches depend on the match depth and do not use the
* cumulative hash value.
*/
const char *
previous_occurance(Game game_details, unsigned plycount)
{
const char *original_filename = NULL;
if (GlobalState.use_virtual_hash_table) {
original_filename = previous_virtual_occurance(game_details);
}
else {
/* Are we keeping this information? */
if (GlobalState.suppress_duplicates ||
GlobalState.suppress_originals ||
GlobalState.fuzzy_match_duplicates ||
GlobalState.duplicate_file != NULL) {
Boolean duplicate = FALSE;
// Entry index.
unsigned ix;
HashLog *entry;
ix = game_details.final_hash_value % LOG_TABLE_SIZE;
entry = LogTable[ix];
/* Check for non-fuzzy matches first. */
while (entry != NULL && !duplicate) {
if (entry->final_hash_value == game_details.final_hash_value &&
entry->cumulative_hash_value == game_details.cumulative_hash_value) {
/* An exact match. */
duplicate = TRUE;
/* Determine where it first occurred. */
original_filename = input_file_name(entry->file_number);
}
else {
entry = entry->next;
}
}
if (!duplicate && GlobalState.fuzzy_match_duplicates) {
ix = game_details.fuzzy_duplicate_hash % LOG_TABLE_SIZE;
entry = LogTable[ix];
while (entry != NULL && !duplicate) {
if (GlobalState.fuzzy_match_depth == 0 &&
entry->final_hash_value == game_details.final_hash_value) {
/* Accept positional match at the end of the game. */
duplicate = TRUE;
}
else {
/* Need to check at the fuzzy_match_depth. */
if (entry->final_hash_value == game_details.fuzzy_duplicate_hash) {
duplicate = TRUE;
}
}
if (duplicate) {
/* We have a match.
* Determine where it first occurred.
*/
original_filename = input_file_name(entry->file_number);
}
else {
entry = entry->next;
}
}
}
if (!duplicate) {
/* First occurrence, so add it to the log. */
entry = (HashLog *) malloc_or_die(sizeof (*entry));
if (!GlobalState.fuzzy_match_duplicates) {
/* Store the two hash values. */
entry->final_hash_value = game_details.final_hash_value;
entry->cumulative_hash_value = game_details.cumulative_hash_value;
}
else if (GlobalState.fuzzy_match_depth > 0 &&
plycount >= GlobalState.fuzzy_match_depth) {
/* Store just the hash value from the fuzzy depth. */
entry->final_hash_value = game_details.fuzzy_duplicate_hash;
entry->cumulative_hash_value = 0;
}
else {
/* Store the two hash values. */
entry->final_hash_value = game_details.final_hash_value;
entry->cumulative_hash_value = game_details.cumulative_hash_value;
}
entry->file_number = current_file_number();
/* Link it into the head at this index. */
entry->next = LogTable[ix];
LogTable[ix] = entry;
}
/* Without a filename, suppressing duplicates on stdin does not work. */
if(duplicate && original_filename == NULL) {
original_filename = "_stdin_";
}
}
}
return original_filename;
}
/* Define a table to hold the zobrist/polyglot hash codes of starting positions.
* Size should be a prime number for collision avoidance.
*/
#define SETUP_TABLE_SIZE 31957
static HashLog *polyglot_codes_of_interest[SETUP_TABLE_SIZE];
/* Whether the standard starting position has been seen in the
* games processed. This avoids having to generate the zobrist
* hash for all games that have no Setup/FEN tags.
*/
static Boolean standard_start_seen = FALSE;
/* Check whether the starting position of the given game
* has been met before.
* Return FALSE if duplicate starting positions are not being
* deleted or if the current position has not been met before.
* Otherwise return TRUE.
*/
Boolean check_duplicate_setup(const Game *game_details)
{
Boolean keep = TRUE;
if(GlobalState.delete_same_setup) {
if(game_details->tags[FEN_TAG] != NULL) {
uint64_t hash = generate_zobrist_hash_from_fen(game_details->tags[FEN_TAG]);
unsigned ix = hash % SETUP_TABLE_SIZE;
Boolean found = FALSE;
for (HashLog *entry = polyglot_codes_of_interest[ix]; !found && (entry != NULL);
entry = entry->next) {
/* We can test against just the position value. */
if (entry->final_hash_value == hash) {
found = TRUE;
}
}
if(found) {
keep = FALSE;
}
else {
HashLog *entry = (HashLog *) malloc_or_die(sizeof (*entry));
/* We don't include the cumulative hash value as this
* is the starting position.
*/
entry->cumulative_hash_value = 0;
entry->final_hash_value = hash;
/* Link it into the head at this index. */
entry->next = polyglot_codes_of_interest[ix];
polyglot_codes_of_interest[ix] = entry;
}
}
else if(standard_start_seen) {
keep = FALSE;
}
else {
standard_start_seen = TRUE;
}
}
return keep;
}

66
pgn-extract/hashing.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Define a type to hold hash values of interest.
* This is used both to aid in duplicate detection
* and in finding positional variations.
*/
#ifndef HASHING_H
#define HASHING_H
typedef struct HashLog {
/* Store both the final position hash value and
* the cumulative hash value for a game.
*/
HashCode final_hash_value;
HashCode cumulative_hash_value;
/* Record the file list index for the file this game was first found in. */
unsigned file_number;
struct HashLog *next;
} HashLog;
/*
* A structure for counting the number of times a position arises
* in a game.
*/
typedef struct PositionCount {
HashCode hash_value;
Colour to_move;
unsigned short castling_rights;
Rank ep_rank;
Col ep_col;
unsigned count;
struct PositionCount *next;
} PositionCount;
Boolean check_duplicate_setup(const Game *game_details);
Boolean check_for_only_repetition(PositionCount *position_counts);
void clear_duplicate_hash_table(void);
PositionCount *copy_position_count_list(PositionCount *original);
void free_position_count_list(PositionCount *position_counts);
void init_duplicate_hash_table(void);
PositionCount *new_position_count_list(const Board *board);
const char *previous_occurance(Game game_details, unsigned plycount);
unsigned update_position_counts(PositionCount *position_counts, const Board *board);
#endif // HASHING_H

2422
pgn-extract/help.html Normal file

File diff suppressed because it is too large Load Diff

217
pgn-extract/index.html Normal file
View File

@@ -0,0 +1,217 @@
<!DOCTYPE HTML>
<html>
<head>
<title>pgn-extract: Portable Game Notation (PGN) Manipulator for Chess Games</title>
<link rev="made" href="mailto:d.j.barnes @ kent.ac.uk">
<meta name="Author" content="David J. Barnes">
<meta name="Description"
CONTENT="Directory with source of program to manipulate
chess games recorded in Portable Game Notation (PGN)
format">
<meta name="Keywords" content="Chess PGN Portable Game Notation
Database
pgn-extract">
<link href="style.css" rel="stylesheet" type="text/css" media="all">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-2248758-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-2248758-2');
</script>
</head>
<body>
<div id="body">
<div id="banner-wrapper">
<div id="banner">
<h1 align="center">pgn-extract:<br />A Portable Game Notation (PGN) Manipulator for Chess Games<br />
Version 22-11 by <a href="https://www.cs.kent.ac.uk/~djb/">David J. Barnes</a>
(<a href="https://twitter.com/kentdjb">@kentdjb</a>)<br />
<a href="pgn-extract.xml">
<img alt="RSS feed image" src="feed.png" width="25" height="25"></a>
</h1>
</div>
</div>
<div id="page-wrapper">
<div id="page">
<h2>Introduction</h2>
<p>This is the home page for
the <em>pgn-extract</em> program,
which is a <em>command-line</em> program for searching, manipulating and formatting
chess games recorded in the Portable Game Notation (PGN) or something close. It
is capable of handling files containing millions of games. It also recognises Chess960
encodings.
<p>A <a href="https://www.cs.kent.ac.uk/people/staff/djb/pgn-extract/help.html">full
description of pgn-extract's functionality</a> is available and included
with the sources.
<p>Here you can find the C source code and Windows binaries for the current
version.
pgn-extract compiles and runs under Windows, Linux and Mac OS X.
This program is made available under the terms of the
<a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/COPYING">GNU
General Public License (Version 3).</a>
<h2>Getting-started video for Windows users</h2>
<p>For Windows users who are really only interested in getting
the binary working, there is <a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/intro.mp4">a short introductory video</a>.
<h2>Overview</h2>
<p>The program is designed to make it easy to extract and format selected games from a
PGN format data file based on a wide variety of criteria.
The criteria include:
<ul>
<li><p>textual move sequences;</p></li>
<li><p>the position reached after a sequence of moves;</p></li>
<li><p>information in the tag fields;</p></li>
<li><p>fuzzy board position;</p></li>
<li><p>and material balance in the ending.</p></li>
</ul>
<p>Over the on-going 20+ year course of its development, it has also added
lots of features for controlling what is output (e.g., different
algebraic formats, EPD, no move numbers, restricting game length, etc.)
<p>The program includes a semantic analyser which will
report errors in game scores and it is also able to detect duplicate
games found in its input files.
<p>The range of input move formats accepted is fairly wide.
The output is normally in English Standard
Algebraic Notation (SAN) but this can be varied to long-algebraic or UCI,
for instance.
<p>Extracted games may be written out either including or excluding
comments, NAGs, variations, move numbers, tags and/or results.
Games may be given ECO classifications
derived from the accompanying file eco.pgn, or a customised version
provided by the user.
<p>The program is designed to be relatively memory-friendly, so it
does not retain a game's moves in memory once it has been processed.
This also makes it suitable for bulk processing very large collections of games
- it can efficiently process files containing several millions of games.
<p>Use the <em>--help</em> argument to the program to
get the full lists of arguments.
<h2>New in recent versions</h2>
<p>These are the main changes in the most recent versions:
<ul>
<li><p>Extended matching of TimeControl to include the formats
of sudden death and sandclock.
<li><p>Added --detag to delete tags that are not required.
<li><p>Added --addfencastling to add potentially missing castling rights to FEN tags.
<li><p>Made duplicate suppression work with input from stdin.
<li><p>Added --deletesamesetup to identify unique starting positions.
<li><p>Added -Wfen to output a game as a sequence of FEN positions.
</ul>
<h2>Available Files</h2>
<p>You can take a copy of the full source and
documentation as either
<a
href="https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-11.tgz">pgn-extract-22-11.tgz</a>
or
<a
href="https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-11.zip">pgn-extract-22-11.zip</a>.
Alternatively, a Windows
<a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract.exe">64-bit</a>
binary is also available.
</p>
<table>
<tr>
<td align="center"><b>Name</b></td>
<td align="center"><b>Description</b></td>
<td align="center"><b>Size</b></td>
<td align="center"><b>Date</b></td>
</tr>
<tr valign="top">
<td><a
href="https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-11.tgz">pgn-extract-22-11.tgz</a><br>
<td>GZipped tar file
of the complete source of the latest version of the program.<br>
Includes <a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/help.html">usage documentation</a>,
Makefile for compilation and
<a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/eco.pgn">eco.pgn</a> file for ECO classification.</td>
<td align="right">424K bytes &nbsp;</td><td>03 May 2022</td>
</tr>
<tr valign="top">
<td><a
href="https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-11.zip">pgn-extract-22-11.zip</a></td>
<td>Zipped file of the complete source of the latest version of the program.<br>
Includes <a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/help.html">usage documentation</a>, Makefile for compilation and
<a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/eco.pgn">eco.pgn</a> file for ECO classification.</td>
<td align="right">582K bytes &nbsp;</td><td>03 May 2022</td>
</tr>
<tr>
<td><a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract.exe">pgn-extract.exe</a></td>
<td>Windows 64-bit binary of the latest version of the program.</td>
<td align="right">1.2M bytes &nbsp;</td><td>03 May 2022</td>
</tr>
<tr>
<td><a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/eco.zip">eco.zip</a></td>
<td>Zipped version of <a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/eco.pgn">eco.pgn</a>.</td>
<td align="right">32K bytes &nbsp;</td><td></td>
</tr>
<tr valign="top">
<td><a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/eco.pgn">eco.pgn</a></td>
<td>File of openings with PGN classification.<br>
This file is already included in the source archives.
</td>
<td align="right">254K bytes &nbsp;</td><td></td>
</tr>
<tr>
<td><a href="https://www.cs.kent.ac.uk/~djb/pgn-extract/COPYING">COPYING</a></td>
<td>GNU General Public License (version 3).</td>
<td align="right">35K bytes &nbsp;</td><td>&nbsp;</td>
</tr>
</table>
<h2>Blog post about data mining with pgn-extract</h2>
<p>In October 2018 I wrote <a href="http://blogs.kent.ac.uk/djb/2018/10/14/data-mining-with-pgn-extract/">blog post</a>
about using pgn-extract to mine a PGN database.
As an example it looks at the effect of having a bishop pair versus a knight pair.
<h2>Answers on Chess StackExchange using pgn-extract</h2>
<p>I am active on <a href="https://chess.stackexchange.com/">Chess StackExchange</a> as
<a href="https://chess.stackexchange.com/users/12951/kentdjb">kentdjb</a>
and aim to respond to pgn-extract related questions, although email to me is my preferred way to raise
potential issues with the program.
<p>From time to time, I have provided answers to questions that involve
the use of pgn-extract for analysis tasks:
<ul>
<li><p><a href="https://chess.stackexchange.com/questions/23938/is-there-a-record-for-threefold-repetition-for-when-the-claimed-positions-are-th/24276#24276">Three-fold repetition</a>.
<li><p><a href="https://chess.stackexchange.com/questions/24166/what-professional-game-has-the-quickest-sequence-starting-from-move-one-to-qua/24274#24274">Quadrupled pawns</a>.
<li><p><a href="https://chess.stackexchange.com/questions/24245/how-often-does-castling-occur-in-grandmaster-games/24247#24247">Frequency of occurrence of castlng</a>.
</ul>
<h2>Feedback</h2>
<p>Feedback and suggestions for further features are always welcome, although I can't always
promise to undertake significant development work.
<hr>
</div>
</div>
<div id="footer">
<address>
<p>&#169; 1994-2022 David J. Barnes<br />
<a href="https://www.cs.kent.ac.uk/~djb/">My home page</a> at the University of Kent.<br />
<a href="mailto:d.j.barnes @ kent.ac.uk">d.j.barnes @ kent.ac.uk</a><br />
<a href="https://twitter.com/kentdjb">@kentdjb</a><br />
Last updated: 15th August 2022: version 22-11 released.<br />
</p>
</address>
</div>
</div>
</body>
</html>

1682
pgn-extract/lex.c Normal file

File diff suppressed because it is too large Load Diff

98
pgn-extract/lex.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Define a type to make it easy to return where we are
* in the input line. This type is returned from those functions
* that may modify the line/linep pair in next_token().
*/
#ifndef LEX_H
#define LEX_H
typedef struct{
/* Start of the malloc'ed line. */
char *line;
/* The next char to access in line, if line is not NULL. */
unsigned char *linep;
/* What token resulted. */
TokenType token;
} LinePair;
/* Define a type to hold a list of input files. */
typedef struct {
/* The list should have a (char *)NULL on the end. */
const char **files;
SourceFileType *file_type;
/* Keep track of the number of files in the list. */
unsigned num_files;
/* Keep track of how many the list may hold. */
unsigned max_files;
} FILE_LIST;
#if 1
#define RUSSIAN_KNIGHT_OR_KING (0x008a)
#define RUSSIAN_KING_SECOND_LETTER (0x00e0)
#define RUSSIAN_QUEEN (0x0094)
#define RUSSIAN_ROOK (0x008b)
#define RUSSIAN_BISHOP (0x0091)
#define RUSSIAN_PAWN (0x00af)
#else
#define RUSSIAN_KNIGHT_OR_KING (0x00eb)
#define RUSSIAN_KING_SECOND_LETTER (0x00d2)
#define RUSSIAN_QUEEN (0x00e6)
#define RUSSIAN_ROOK (0x00ec)
#define RUSSIAN_BISHOP (0x00f3)
#endif
/* Define a macro for checking the value of a char against
* one of the Russian piece letters.
*/
#define RUSSIAN_PIECE_CHECK(c) ((c) & 0x00ff)
/* Shared prototypes for the non-static functions in the
* lexical analyser.
*/
void add_filename_to_source_list(const char *filename,SourceFileType file_type);
void add_filename_list_from_file(FILE *fp,SourceFileType file_type);
unsigned current_file_number(void);
void free_move_list(Move *move_list);
LinePair gather_tag(char *line, unsigned char *linep);
LinePair gather_string(char *line, unsigned char *linep);
void init_lex_tables(void);
const char *input_file_name(unsigned file_number);
unsigned long get_line_number(void);
Boolean is_character_class(unsigned char ch, TokenType character_class);
Boolean is_suppressed_tag(TagName tag);
char *next_input_line(FILE *fp);
TokenType next_token(void);
Boolean open_eco_file(const char *eco_file);
Boolean open_first_file(void);
void print_error_context(FILE *fp);
char *read_line(FILE *fpin);
void reset_line_number(void);
void restart_lex_for_new_game(void);
void save_assessment(const char *assess);
TokenType skip_to_next_game(TokenType token);
void suppress_tag(const char *tag_string);
const char *tag_header_string(TagName tag);
void yyerror(const char *s);
int yywrap(void);
#endif // LEX_H

73
pgn-extract/lines.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bool.h"
#include "mymalloc.h"
#include "lines.h"
/* Define a character that may be used to comment a line in, e.g.
* the variations files.
* Use the PGN escape mechanism character, for consistency.
*/
#define COMMENT_CHAR '%'
/* Return TRUE if line contains a non-space character, but
* is not a comment line.
*/
Boolean
non_blank_line(const char *line)
{
Boolean blank = TRUE;
if (line != NULL) {
if (comment_line(line)) {
/* Comment lines count as blanks. */
}
else {
while (blank && (*line != '\0')) {
if (!isspace((int) *line)) {
blank = FALSE;
}
else {
line++;
}
}
}
}
return !blank;
}
Boolean
blank_line(const char *line)
{
return !non_blank_line(line);
}
/* Should the given line be regarded as a comment line? */
Boolean
comment_line(const char *line)
{
return *line == COMMENT_CHAR;
}

30
pgn-extract/lines.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef LINES_H
#define LINES_H
Boolean non_blank_line(const char *line);
Boolean blank_line(const char *line);
Boolean comment_line(const char *line);
#endif // LINES_H

892
pgn-extract/lists.c Normal file
View File

@@ -0,0 +1,892 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <regex.h>
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "lists.h"
#include "taglist.h"
#include "moves.h"
/* Define a type to permit tag strings to be associated with
* a TagOperator for selecting relationships between them
* and a game to be matched.
*/
typedef struct tag_selection {
char *tag_string;
TagOperator operator;
} TagSelection;
/* Definitions for maintaining arrays of tag strings.
* These arrays are used for various purposes:
* lists of white/black players to extract on.
* lists of other criteria to extract on.
*/
typedef struct {
/* How many elements we have currently allocated for.
* If this is > 0 then we should always have allocated exactly
* one more than this number to simplify the (char **) NULL
* termination of the list.
*/
unsigned num_allocated_elements;
/* num_used_elements should always be <= num_allocated elements. */
unsigned num_used_elements;
/* The list of elements.
* Elements 0 .. num_used_elements point to null-terminated strings.
* list[num_used_elements] == (char **) NULL once the list is complete.
*/
TagSelection *tag_strings;
} StringArray;
/* Functions to allow creation of string lists. */
/* Allow a string list for every known tag.
* It is important that these lists should be initialised to
* { 0, 0, (TagSelection *) NULL }
* which happens by default, anyway.
* This array, and its length (tag_list_length) are initialised
* by calling init_tag_lists.
*/
static StringArray *TagLists;
static int tag_list_length = 0;
static char *soundex(const char *str);
static Boolean check_list(int tag, const char *tag_string, const StringArray *list);
static Boolean check_time_period(const char *tag_string, unsigned period, const StringArray *list);
void init_tag_lists(void)
{
int i;
tag_list_length = ORIGINAL_NUMBER_OF_TAGS;
TagLists = (StringArray *) malloc_or_die(tag_list_length * sizeof (*TagLists));
for (i = 0; i < tag_list_length; i++) {
TagLists[i].num_allocated_elements = 0;
TagLists[i].num_used_elements = 0;
TagLists[i].tag_strings = (TagSelection *) NULL;
}
}
/*
* Extend the tag list to the new length.
*/
static void
extend_tag_list_length(int new_length)
{
if (new_length < tag_list_length) {
fprintf(GlobalState.logfile,
"Internal error: inappropriate call to extend_tag_list_length().\n");
fprintf(GlobalState.logfile,
"New length of %d is not greater than existing length of %d\n",
new_length, tag_list_length);
exit(1);
}
else {
int i;
TagLists = (StringArray *) realloc_or_die((void *) TagLists,
new_length * sizeof (*TagLists));
for (i = tag_list_length; i < new_length; i++) {
TagLists[i].num_allocated_elements = 0;
TagLists[i].num_used_elements = 0;
TagLists[i].tag_strings = (TagSelection *) NULL;
}
tag_list_length = new_length;
}
}
/* Add str to the list of strings in list.
* List may be a new list, in which case space is allocated
* for it.
* Return the index on success, otherwise -1.
*/
static int
add_to_taglist(const char *str, StringArray *list)
{
Boolean everything_ok = TRUE;
if (list->num_allocated_elements == list->num_used_elements) {
/* We need more space. */
if (list->num_allocated_elements == 0) {
/* No elements in the list. */
list->tag_strings = (TagSelection *) malloc_or_die((INIT_LIST_SPACE + 1) *
sizeof (TagSelection));
if (list->tag_strings != NULL) {
list->num_allocated_elements = INIT_LIST_SPACE;
list->num_used_elements = 0;
}
else {
everything_ok = FALSE;
}
}
else {
list->tag_strings = (TagSelection *) realloc_or_die((void *) list->tag_strings,
(list->num_allocated_elements + MORE_LIST_SPACE + 1) *
sizeof (TagSelection));
if (list->tag_strings != NULL) {
list->num_allocated_elements += MORE_LIST_SPACE;
}
else {
everything_ok = FALSE;
}
}
}
if (everything_ok) {
/* There is space. */
const unsigned len = strlen(str) + 1;
unsigned ix = list->num_used_elements;
list->tag_strings[ix].operator = NONE;
list->tag_strings[ix].tag_string = (char *) malloc_or_die(len);
if (list->tag_strings[ix].tag_string != NULL) {
strcpy(list->tag_strings[ix].tag_string, str);
list->num_used_elements++;
/* Make sure that the list is properly terminated at all times. */
list->tag_strings[ix + 1].tag_string = NULL;
return (int) ix;
}
else {
return -1;
}
}
else {
return -1;
}
}
/* Simple soundex code supplied by John Brogan
* (jwbrogan@unix2.netaxs.com), 26th Aug 1994.
* John writes:
* "In recognition of the large number of strong players from countries
* with Slavic based languages, I tried to tailor the soundex code
* to match any reasonable transliteration of a Slavic name into
* English. Thus, Nimzovich will match Nimsowitsch, Tal will match
* Talj, etc. Unfortunately, in order to be sure not to miss any
* valid matches, I had to make the code so tolerant that it sometimes
* comes up with some wildly false matches. This, to me, is better
* than missing some games, but your mileage may differ."
*
* This looks like it was originally derived from the public domain
* version released by N. Dean Pentcheff, 1989, which was, itself,
* based on that in D.E. Knuth's "The art of computer programming.",
* Volume 3: Sorting and searching. Addison-Wesley Publishing Company:
* Reading, Mass. Page 392.
* Amended by David Barnes, 2nd Sep 1994.
*/
/* Define a maximum length for the soundex result. */
#define MAXSOUNDEX 50
/* Calculate a soundex string for instr.
* The space used is statically allocated, so the caller
* will have to allocate its own for the result if it
* to be retained across different calls.
*/
static char *
soundex(const char *str)
{
static char sbuf[MAXSOUNDEX + 1];
/* An index into sbuf. */
unsigned sindex = 0;
/* Keep track of the last character to compress repeated letters. */
char lastc = ' ';
/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
const char *mapping = "01230120002455012622011202";
char initial_letter = *str;
/* Special case for names that begin with 'J',
* otherwise Janosevic == Nimzovich.
* In addition, we really want Yusupov to match Jusupov.
*/
if (islower((int) initial_letter)) {
initial_letter = toupper(initial_letter);
}
if ((initial_letter == 'Y') || (initial_letter == 'J')) {
sbuf[sindex] = '7';
str++;
sindex++;
}
while ((*str != '\0') && (sindex < MAXSOUNDEX)) {
char ch = *str;
/* We are only interested in alphabetics, and duplicate
* characters are reduced to singletons.
*/
if (isalpha((int) ch) && (ch != lastc)) {
char translation;
if (islower((int) ch)) {
ch = toupper(ch);
}
/* Pick up the translation. */
translation = mapping[ch - 'A'];
if ((translation != '0') && (translation != lastc)) {
sbuf[sindex] = translation;
sindex++;
lastc = translation;
}
}
str++;
}
sbuf[sindex] = '\0';
return (sbuf);
}
/* Return TRUE if tag is one on which soundex matching should
* be used, if requested.
*/
static Boolean
soundex_tag(int tag)
{
Boolean use_soundex = FALSE;
switch (tag) {
case WHITE_TAG:
case BLACK_TAG:
case PSEUDO_PLAYER_TAG:
case EVENT_TAG:
case SITE_TAG:
case ANNOTATOR_TAG:
use_soundex = TRUE;
break;
}
return use_soundex;
}
/* Add tagstr to the list of tags to be matched.
* If we are using soundex matching, then store
* its soundex version rather than its plain text.
*/
void
add_tag_to_list(int tag, const char *tagstr, TagOperator operator)
{
if (tag >= tag_list_length) {
/* A new tag - one without a pre-defined _TAG #define.
* Make sure there is room for it in TagList.
*/
extend_tag_list_length(tag + 1);
}
if(tag == FEN_TAG) {
add_fen_pattern_match(tagstr, FALSE, NULL);
}
else if ((tag >= 0) && (tag < tag_list_length)) {
const char *string_to_store = tagstr;
int ix;
if (GlobalState.use_soundex) {
if (soundex_tag(tag)) {
string_to_store = soundex(tagstr);
}
}
ix = add_to_taglist(string_to_store, &TagLists[tag]);
if (ix >= 0) {
TagLists[tag].tag_strings[ix].operator = operator;
}
/* Ensure that we know we are checking tags. */
GlobalState.check_tags = TRUE;
}
else {
fprintf(GlobalState.logfile,
"Illegal tag number %d in add_tag_to_list.\n", tag);
}
}
/* Argstr is an extraction argument.
* The type of argument is indicated by the first letter of
* argstr:
* a -- annotator of the game
* b -- player of the black pieces
* d -- date of the game
* e -- ECO code
* p -- player of either colour
* r -- result
* w -- player of the white pieces
* The remainder of argstr is the argument string to be entered
* into the appropriate list.
*/
void
extract_tag_argument(const char *argstr)
{
const char *arg = &(argstr[1]);
switch (*argstr) {
case 'a':
add_tag_to_list(ANNOTATOR_TAG, arg, NONE);
break;
case 'b':
add_tag_to_list(BLACK_TAG, arg, NONE);
break;
case 'd':
add_tag_to_list(DATE_TAG, arg, NONE);
break;
case 'e':
add_tag_to_list(ECO_TAG, arg, NONE);
break;
case 'f':
add_tag_to_list(FEN_TAG, arg, NONE);
break;
case 'h':
add_tag_to_list(HASHCODE_TAG, arg, NONE);
break;
case 'p':
add_tag_to_list(PSEUDO_PLAYER_TAG, arg, NONE);
break;
case 'r':
add_tag_to_list(RESULT_TAG, arg, NONE);
break;
case 't':
add_tag_to_list(TIME_CONTROL_TAG, arg, NONE);
break;
case 'w':
add_tag_to_list(WHITE_TAG, arg, NONE);
break;
default:
fprintf(GlobalState.logfile,
"Unknown type of tag extraction argument: %s\n",
argstr);
exit(1);
break;
}
}
/* Determine whether lhs operator rhs is TRUE or FALSE. */
static Boolean
relative_numeric_match(TagOperator operator, double lhs, double rhs)
{
switch (operator) {
case LESS_THAN:
return lhs < rhs;
case LESS_THAN_OR_EQUAL_TO:
return lhs <= rhs;
case GREATER_THAN:
return lhs > rhs;
case GREATER_THAN_OR_EQUAL_TO:
return lhs >= rhs;
case EQUAL_TO:
return lhs == rhs;
case NOT_EQUAL_TO:
return lhs != rhs;
case NONE:
fprintf(GlobalState.logfile, "Internal error: NONE in call to relative_numeric_match.\n");
return FALSE;
default:
fprintf(GlobalState.logfile, "Internal error: missing case in call to relative_numeric_match.\n");
return FALSE;
}
}
/* Check for one of list->strings matching the date_string.
* Return TRUE on match, FALSE on failure.
* It is only necessary for a prefix of tag to match
* the string.
*/
/* Set limits on the allowable ranges for dates extracted from games.
* Because of century changes, it is difficult to know what
* best to do with two digit year numbers; so exclude them.
*/
#define MINDATE 100
#define MAXDATE 3000
static Boolean
check_date(const char *date_string, const StringArray *list)
{
unsigned list_index;
/* Care needed because dates with operators must be ANDed and
* dates without operators must be ORed.
* The first match is used to set wanted properly for the first time.
*/
Boolean wanted = FALSE;
unsigned game_year, game_month = 1, game_day = 1;
if(sscanf(date_string, "%u", &game_year) == 1) {
/* Try to extract month and day from the game's date string. */
sscanf(date_string, "%*u.%u.%u", &game_month, &game_day);
double encoded_game_date = 10000 * game_year + 100 * game_month + game_day;
for (list_index = 0; list_index < list->num_used_elements; list_index++) {
const char *list_string = list->tag_strings[list_index].tag_string;
TagOperator operator = list->tag_strings[list_index].operator;
if (*list_string == 'b') {
operator = LESS_THAN;
list_string++;
}
else if (*list_string == 'a') {
operator = GREATER_THAN;
list_string++;
}
else {
/* No prefix. */
}
if (operator != NONE) {
/* We have a relational comparison. */
unsigned list_year, list_month = 1, list_day = 1;
if (sscanf(list_string, "%u", &list_year) == 1) {
if((game_year > MINDATE) && (game_year < MAXDATE)) {
sscanf(list_string, "%*u.%u.%u", &list_month, &list_day);
double encoded_list_date = 10000 * list_year + 100 * list_month + list_day;
Boolean matches = relative_numeric_match(operator, encoded_game_date, encoded_list_date);
if (list_index == 0) {
wanted = matches;
}
else {
wanted = wanted && matches;
}
}
else {
/* Bad format, or out of range. Assume not wanted.
* Don't report the bad date in the game.
*/
wanted = FALSE;
}
}
else {
/* Bad format. Assume not wanted. */
wanted = FALSE;
/* While this will give an error for each game, a bad date
* in the list of tags to be matched needs reporting.
*/
fprintf(GlobalState.logfile,
"Failed to extract year from %s.\n", list_string);
}
}
else {
/* No need to check if we already have a match. */
if (list_index == 0 || !wanted) {
/* Just a straight prefix match. */
wanted = strncmp(date_string, list_string, strlen(list_string)) == 0;
}
}
}
}
return wanted;
}
/* Check whether the TimeControl value matches the requirements. */
static Boolean
check_time_control(const char *tc_string, const StringArray *list)
{
Boolean wanted = FALSE;
if(*tc_string == '\0' || *tc_string == '?' || *tc_string == '-') {
/* Nothing to compare. */
}
else {
/* Examine just the first if there are multiple controls. */
char *control = copy_string(tc_string);
char *sep = strchr(control, ':');
if(sep != NULL) {
*sep = '\0';
}
if(strchr(control, '+') != NULL) {
/* Period+increment. */
unsigned period;
if(sscanf(control,"%u", &period) == 1) {
wanted = check_time_period(control, period, list);
}
}
else if(*control == '*') {
/* Sandclock. */
unsigned period;
if(sscanf(control + 1,"%u", &period) == 1) {
wanted = check_time_period(control, period, list);
}
}
else {
/* Look for the format moves/seconds. */
char *slash = strchr(control, '/');
if(slash != NULL) {
unsigned period;
if(sscanf(slash + 1, "%u", &period) == 1) {
wanted = check_time_period(control, period, list);
}
}
else if(isdigit(*control)) {
/* Sudden death. */
const char *digit = control;
while(isdigit(*digit)) {
digit++;
}
if(*digit == '\0') {
unsigned period;
if(sscanf(control,"%u", &period) == 1) {
wanted = check_time_period(control, period, list);
}
}
}
}
(void) free((void *) control);
}
return wanted;
}
/* Compare the given time period against those provided for matches.
* Return TRUE if a match is found.
*/
static Boolean
check_time_period(const char *tag_string, unsigned period, const StringArray *list)
{
Boolean wanted = FALSE;
unsigned list_index;
for (list_index = 0; (list_index < list->num_used_elements) && !wanted; list_index++) {
const char *list_string = list->tag_strings[list_index].tag_string;
TagOperator operator = list->tag_strings[list_index].operator;
if (operator != NONE) {
/* We have a relational comparison. */
unsigned list_period;
if ((sscanf(list_string, "%u", &list_period) == 1)) {
wanted = relative_numeric_match(operator, (double) period, (double) list_period);
}
else {
/* Bad format. */
}
}
else {
/* Just a straight prefix match. */
if (strncmp(tag_string, list_string, strlen(list_string)) == 0) {
wanted = TRUE;
}
}
}
return wanted;
}
/* Check whether the Elo value matches any of those
* in the list.
*/
static Boolean
check_elo(const char *elo_string, StringArray *list)
{
unsigned list_index;
Boolean wanted = FALSE;
unsigned game_elo;
if(sscanf(elo_string, "%u", &game_elo) == 1) {
for (list_index = 0; (list_index < list->num_used_elements) && !wanted; list_index++) {
const char *list_string = list->tag_strings[list_index].tag_string;
TagOperator operator = list->tag_strings[list_index].operator;
if (operator != NONE) {
/* We have a relational comparison. */
unsigned list_elo;
if ((sscanf(list_string, "%u", &list_elo) == 1)) {
wanted = relative_numeric_match(operator, (double) game_elo, (double) list_elo);
}
else {
/* Bad format, or out of range. Assume not wanted. */
wanted = FALSE;
}
}
else {
/* Just a straight prefix match. */
if (strncmp(elo_string, list_string, strlen(list_string)) == 0) {
wanted = TRUE;
}
}
}
}
return wanted;
}
/* Check for matches of tag_string in list->strings.
* Return TRUE on match, FALSE on failure.
* For non-numeric tags, ANY match is considered.
* Either a prefix of tag is checked, or anywhere
* in the tag if tag_match_anywhere is set.
* For numeric tags with relational operators, ALL operators must match.
*/
static Boolean
check_list(int tag, const char *tag_string, const StringArray *list)
{
unsigned list_index;
Boolean wanted = FALSE;
const char *search_str;
Boolean tag_string_is_numeric;
/* Whether to consider possible numeric range comparison
* in the case of numeric tag values, if there is no
* other match.
*/
Boolean possible_range_check = FALSE;
/* Where there is a possible regex check. */
Boolean possible_regex_check = FALSE;
const char *t;
if (GlobalState.use_soundex && soundex_tag(tag)) {
search_str = soundex(tag_string);
}
else {
search_str = tag_string;
}
/* Determine whether the search string is numeric or not.
* If it is numeric then it could be used in a
* relational match.
*/
t = search_str;
if(*t == '+' || *t == '-') {
t++;
}
/* Potential for imprecision in that multiple '.' would be accepted. */
while(isdigit(*t) || *t == '.') {
t++;
}
tag_string_is_numeric = *t == '\0';
for (list_index = 0; (list_index < list->num_used_elements) && !wanted;
list_index++) {
const TagSelection *selection = &list->tag_strings[list_index];
const char *list_string = selection->tag_string;
if (GlobalState.tag_match_anywhere) {
/* Match anywhere in the tag. */
if (strstr(search_str, list_string) != NULL) {
wanted = TRUE;
}
}
else {
/* Match only at the beginning of the tag. */
if (strncmp(search_str, list_string, strlen(list_string)) == 0) {
wanted = TRUE;
}
}
if(!wanted && selection->operator != NONE) {
if(tag_string_is_numeric) {
/* Defer to a later check. */
possible_range_check = TRUE;
}
if(selection->operator == REGEX) {
/* Defer to a later check. */
possible_regex_check = TRUE;
}
}
}
if(! wanted) {
if(possible_range_check) {
/* Check the relational operators.
* This requires ALL to match rather than ANY.
* There will be at least one comparison, so this
* initial value of wanted will be discarded before
* the end of the method.
*/
wanted = TRUE;
for (list_index = 0; (list_index < list->num_used_elements) && wanted;
list_index++) {
const TagSelection *selection = &list->tag_strings[list_index];
switch(selection->operator) {
case EQUAL_TO:
case NOT_EQUAL_TO:
case LESS_THAN:
case GREATER_THAN:
case LESS_THAN_OR_EQUAL_TO:
case GREATER_THAN_OR_EQUAL_TO:
{
const char *list_string = selection->tag_string;
double tag_value, list_value;
if(sscanf(search_str, "%lf", &tag_value) == 1 &&
sscanf(list_string, "%lf", &list_value) == 1) {
wanted = relative_numeric_match(selection->operator,
tag_value, list_value);
}
}
break;
case NONE:
break;
default:
fprintf(GlobalState.logfile, "Internal error: missing case in call to check_list.\n");
break;
}
}
}
if(! wanted && possible_regex_check) {
for (list_index = 0; (list_index < list->num_used_elements) && ! wanted;
list_index++) {
const TagSelection *selection = &list->tag_strings[list_index];
if(selection->operator == REGEX) {
const char *list_string = selection->tag_string;
regex_t regex;
if(regcomp(&regex, list_string, 0) == 0) {
if(regexec(&regex, search_str, 0, NULL, 0) == 0) {
wanted = TRUE;
}
}
regfree(&regex);
}
}
}
}
return wanted;
}
/* Check the Tag Details of this current game against those in
* the wanted lists. Check all details apart from any ECO
* tag as this is checked separately by CheckECOTag.
* An empty list implies that there is no restriction on
* the values in the corresponding tag field.
* In consequence, completely empty lists imply that all
* games reaching this far are wanted.
* Return TRUE if wanted, FALSE otherwise.
*/
Boolean
check_tag_details_not_ECO(char *Details[], int num_details)
{
Boolean wanted = TRUE;
int tag;
if (GlobalState.check_tags) {
/* Sanity check. */
if (num_details < tag_list_length) {
fprintf(GlobalState.logfile,
"Internal error: mismatch in tag set lengths in ");
fprintf(GlobalState.logfile,
"CheckTagDetailsNotECO: %d vs %d\n",
num_details, tag_list_length);
exit(1);
}
/* PSEUDO_PLAYER_TAG and PSEUDO_ELO_TAG are treated differently,
* since they have the effect of or-ing together the WHITE_ and BLACK_ lists.
* Otherwise, different tag lists are and-ed.
*/
if (TagLists[PSEUDO_PLAYER_TAG].num_used_elements != 0) {
/* Check both the White and Black lists. */
if (Details[WHITE_TAG] != NULL) {
wanted = check_list(WHITE_TAG, Details[WHITE_TAG],
&TagLists[PSEUDO_PLAYER_TAG]);
/* If we didn't find a player there, try for the opponent. */
if (!wanted && (Details[BLACK_TAG] != NULL)) {
wanted = check_list(BLACK_TAG, Details[BLACK_TAG],
&TagLists[PSEUDO_PLAYER_TAG]);
}
}
else if (Details[BLACK_TAG] != NULL) {
wanted = check_list(BLACK_TAG, Details[BLACK_TAG],
&TagLists[PSEUDO_PLAYER_TAG]);
}
else {
wanted = FALSE;
}
}
if (TagLists[PSEUDO_ELO_TAG].num_used_elements != 0) {
/* Check both the White and Black lists. */
if (Details[WHITE_ELO_TAG] != NULL) {
wanted = check_elo(Details[WHITE_ELO_TAG],
&TagLists[PSEUDO_ELO_TAG]);
/* If we didn't find the ELO there, try for the opponent. */
if (!wanted && (Details[BLACK_ELO_TAG] != NULL)) {
wanted = check_elo(Details[BLACK_ELO_TAG],
&TagLists[PSEUDO_ELO_TAG]);
}
}
else if (Details[BLACK_ELO_TAG] != NULL) {
wanted = check_elo(Details[BLACK_ELO_TAG],
&TagLists[PSEUDO_ELO_TAG]);
}
else {
wanted = FALSE;
}
}
else {
/* No PSEUDO_*_TAG info to check. */
}
/* Check the remaining tags in turn as long as we still have a match. */
for (tag = 0; (tag < tag_list_length) && wanted; tag++) {
if (tag == PSEUDO_PLAYER_TAG) {
}
else if (tag == PSEUDO_ELO_TAG) {
}
else if (tag == ECO_TAG) {
/* This is handled separately. */
}
else if (TagLists[tag].num_used_elements != 0) {
if (Details[tag] != NULL) {
if (tag == DATE_TAG) {
wanted = check_date(Details[tag], &TagLists[DATE_TAG]);
}
else if ((tag == WHITE_ELO_TAG) || (tag == BLACK_ELO_TAG)) {
wanted = check_elo(Details[tag], &TagLists[tag]);
}
else if (tag == TIME_CONTROL_TAG) {
wanted = check_time_control(Details[tag], &TagLists[TIME_CONTROL_TAG]);
}
else {
wanted = check_list(tag, Details[tag], &TagLists[tag]);
}
}
else {
/* Required tag not present. */
wanted = FALSE;
}
}
else {
/* Not used. */
}
}
}
return wanted;
}
/* Check just the ECO tag from the game's tag details. */
Boolean
check_ECO_tag(char *Details[])
{
Boolean wanted = TRUE;
if (GlobalState.check_tags) {
if (TagLists[ECO_TAG].num_used_elements != 0) {
if (Details[ECO_TAG] != NULL) {
wanted = check_list(ECO_TAG, Details[ECO_TAG], &TagLists[ECO_TAG]);
}
else {
/* Required tag not present. */
wanted = FALSE;
}
}
}
return wanted;
}
/* Check whether the tags fit with the setting of GlobalState.setup_status.
* Return TRUE if they do, false otherwise.
*/
Boolean
check_setup_tag(char *Details[])
{
switch (GlobalState.setup_status) {
case SETUP_TAG_OK:
return TRUE;
case NO_SETUP_TAG:
return Details[SETUP_TAG] == NULL;
case SETUP_TAG_ONLY:
return Details[SETUP_TAG] != NULL;
default:
fprintf(GlobalState.logfile, "Internal error: setup status %u not recognised.",
GlobalState.setup_status);
exit(1);
}
}

53
pgn-extract/lists.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Define values for the amount of space to initially malloc
* and incrementally realloc in a list.
*/
#ifndef LISTS_H
#define LISTS_H
#define INIT_LIST_SPACE 10
#define MORE_LIST_SPACE 5
/* Tags to be sought may have an operator to specify the
* relationship between value in the tag list and that in
* the game. For instance, in order to find games before 1962
* use Date < "1962". The < turns into a LESS_THAN operator.
* Potentially any tag may have an operator, but not all make
* sense in all circumstances.
*/
typedef enum {
NONE,
LESS_THAN, GREATER_THAN, EQUAL_TO, NOT_EQUAL_TO,
LESS_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO,
REGEX
} TagOperator;
void extract_tag_argument(const char *argstr);
void add_tag_to_list(int tag,const char *tagstr,TagOperator operator);
Boolean check_tag_details_not_ECO(char *Details[],int num_details);
Boolean check_ECO_tag(char *Details[]);
void init_tag_lists(void);
Boolean check_setup_tag(char *Details[]);
#endif // LISTS_H

442
pgn-extract/main.c Normal file
View File

@@ -0,0 +1,442 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bool.h"
#include "mymalloc.h"
#include "defs.h"
#include "typedef.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
#include "moves.h"
#include "map.h"
#include "lists.h"
#include "output.h"
#include "end.h"
#include "grammar.h"
#include "hashing.h"
#include "argsfile.h"
/* The maximum length of an output line. This is conservatively
* slightly smaller than the PGN export standard of 80.
*/
#define MAX_LINE_LENGTH 75
/* Define a file name relative to the current directory representing
* a file of ECO classificiations.
*/
#ifndef DEFAULT_ECO_FILE
#define DEFAULT_ECO_FILE "eco.pgn"
#endif
/* This structure holds details of the program state
* available to all parts of the program.
* This goes against the grain of good structured programming
* principles, but most of these fields are set from the program's
* arguments and are read-only thereafter. If I had done this in
* C++ there would have been a cleaner interface!
*/
StateInfo GlobalState = {
FALSE, /* skipping_current_game */
FALSE, /* check_only (-r) */
2, /* verbosity level (-s and --quiet) */
TRUE, /* keep_NAGs (-N) */
TRUE, /* keep_comments (-C) */
TRUE, /* keep_variations (-V) */
ALL_TAGS, /* tag_output_form (-7, --notags) */
TRUE, /* match_permutations (-v) */
FALSE, /* positional_variations (-x) */
FALSE, /* use_soundex (-S) */
FALSE, /* suppress_duplicates (-D) */
FALSE, /* suppress_originals (-U) */
FALSE, /* fuzzy_match_duplicates (--fuzzy) */
0, /* fuzzy_match_depth (--fuzzy) */
FALSE, /* check_tags */
FALSE, /* add_ECO (-e) */
FALSE, /* parsing_ECO_file (-e) */
DONT_DIVIDE, /* ECO_level (-E) */
SAN, /* output_format (-W) */
MAX_LINE_LENGTH, /* max_line_length (-w) */
FALSE, /* use_virtual_hash_table (-Z) */
FALSE, /* check_move_bounds (-b) */
FALSE, /* match_only_checkmate (-M) */
FALSE, /* match_only_stalemate (--stalemate) */
TRUE, /* keep_move_numbers (--nomovenumbers) */
TRUE, /* keep_results (--noresults) */
TRUE, /* keep_checks (--nochecks) */
FALSE, /* output_evaluation (--evaluation) */
FALSE, /* keep_broken_games (--keepbroken) */
FALSE, /* suppress_redundant_ep_info (--nofauxep) */
FALSE, /* json_format (--json) */
FALSE, /* tag_match_anywhere (--tagsubstr) */
FALSE, /* match_underpromotion (--underpromotion) */
0, /* depth_of_positional_search */
0, /* num_games_processed */
0, /* num_games_matched */
0, /* games_per_file (-#) */
1, /* next_file_number */
0, /* lower_move_bound */
10000, /* upper_move_bound */
-1, /* output_ply_limit (--plylimit) */
0, /* stability_threshold (--stable) */
1, /* first */
~0, /* game_limit */
0, /* maximum_matches */
0, /* drop_ply_number (--dropply) */
1, /* startply (--startply) */
0, /* check_for_repetition (--repetition) */
0, /* check_for_N_move_rule (--fifty, --seventyfive) */
FALSE, /* output_FEN_string */
FALSE, /* add_FEN_comments (--fencomments) */
FALSE, /* add_hashcode_comments (--hashcomments) */
FALSE, /* add_position_match_comments (--markmatches) */
FALSE, /* output_plycount (--plycount) */
FALSE, /* output_total_plycount (--totalplycount) */
FALSE, /* add_hashcode_tag (--addhashcode) */
FALSE, /* fix_result_tags (--fixresulttags) */
FALSE, /* fix_tag_strings (--fixtagstrings) */
FALSE, /* add_fen_castling (--addfencastling) */
FALSE, /* separate_comment_lines (--commentlines) */
FALSE, /* split_variants (--separatevariants) */
FALSE, /* reject_inconsistent_results (--nobadresults) */
FALSE, /* allow_null_moves (--allownullmoves) */
FALSE, /* allow_nested_comments (--nestedcomments) */
FALSE, /* add_match_tag (--addmatchtag) */
FALSE, /* add_matchlabel_tag (--addlabeltag) */
FALSE, /* only_output_wanted_tags (--xroster) */
FALSE, /* delete_same_setup (--deletesamesetup) */
FALSE, /* lichess_comment_fix (--lichesscommentfix) */
0, /* split_depth_limit */
NORMALFILE, /* current_file_type */
SETUP_TAG_OK, /* setup_status */
EITHER_TO_MOVE, /* whose_move */
"MATCH", /* position_match_comment (--markmatches) */
(char *) NULL, /* FEN_comment_pattern (-Fpattern) */
(char *) NULL, /* drop_comment_pattern (--dropbefore) */
(char *) NULL, /* line_number_marker (--linenumbers) */
(char *) NULL, /* current_input_file */
DEFAULT_ECO_FILE, /* eco_file (-e) */
(FILE *) NULL, /* outputfile (-o, -a). Default is stdout */
(char *) NULL, /* output_filename (-o, -a) */
(FILE *) NULL, /* logfile (-l). Default is stderr */
(FILE *) NULL, /* duplicate_file (-d) */
(FILE *) NULL, /* non_matching_file (-n) */
NULL, /* matching_game_numbers */
NULL, /* next_game_number_to_output */
NULL, /* skip_game_numbers */
NULL, /* next_game_number_to_skip */
};
/* Prepare the output file handles in GlobalState. */
static void
init_default_global_state(void)
{
GlobalState.outputfile = stdout;
GlobalState.logfile = stderr;
set_output_line_length(MAX_LINE_LENGTH);
}
int
main(int argc, char *argv[])
{
int argnum;
/* Prepare global state. */
init_default_global_state();
/* Prepare the Game_Header. */
init_game_header();
/* Prepare the tag lists for -t/-T matching. */
init_tag_lists();
/* Prepare the hash tables for transposition detection. */
init_hashtab();
/* Initialise the lexical analyser's tables. */
init_lex_tables();
/* Allow for some arguments. */
for (argnum = 1; argnum < argc;) {
const char *argument = argv[argnum];
if (argument[0] == '-') {
switch (argument[1]) {
/* Arguments with no additional component. */
case SEVEN_TAG_ROSTER_ARGUMENT:
case DONT_KEEP_COMMENTS_ARGUMENT:
case DONT_KEEP_DUPLICATES_ARGUMENT:
case DONT_KEEP_VARIATIONS_ARGUMENT:
case DONT_KEEP_NAGS_ARGUMENT:
case DONT_MATCH_PERMUTATIONS_ARGUMENT:
case CHECK_ONLY_ARGUMENT:
case KEEP_SILENT_ARGUMENT:
case USE_SOUNDEX_ARGUMENT:
case MATCH_CHECKMATE_ARGUMENT:
case SUPPRESS_ORIGINALS_ARGUMENT:
case USE_VIRTUAL_HASH_TABLE_ARGUMENT:
process_argument(argument[1], "");
argnum++;
break;
/* Argument rewritten as a different one. */
case ALTERNATIVE_HELP_ARGUMENT:
process_argument(HELP_ARGUMENT, "");
argnum++;
break;
/* Arguments where an additional component is required.
* It must be adjacent to the argument and not separated from it.
*/
case TAG_EXTRACTION_ARGUMENT:
process_argument(argument[1], &(argument[2]));
argnum++;
break;
/* Arguments where an additional component is optional.
* If it is present, it must be adjacent to the argument
* letter and not separated from it.
*/
case HELP_ARGUMENT:
case OUTPUT_FORMAT_ARGUMENT:
case USE_ECO_FILE_ARGUMENT:
process_argument(argument[1], &(argument[2]));
argnum++;
break;
/* Long form arguments. */
case LONG_FORM_ARGUMENT:
{
/* How many args (1 or 2) are processed. */
int args_processed;
/* This argument might need the following argument
* as an associated value.
*/
const char *possible_associated_value = "";
if (argnum + 1 < argc) {
possible_associated_value = argv[argnum + 1];
}
/* Find out how many arguments were consumed
* (1 or 2).
*/
args_processed =
process_long_form_argument(&argument[2],
possible_associated_value);
argnum += args_processed;
}
break;
/* Arguments with a required filename component. */
case FILE_OF_ARGUMENTS_ARGUMENT:
case APPEND_TO_OUTPUT_FILE_ARGUMENT:
case CHECK_FILE_ARGUMENT:
case DUPLICATES_FILE_ARGUMENT:
case FILE_OF_FILES_ARGUMENT:
case WRITE_TO_LOG_FILE_ARGUMENT:
case APPEND_TO_LOG_FILE_ARGUMENT:
case NON_MATCHING_GAMES_ARGUMENT:
case WRITE_TO_OUTPUT_FILE_ARGUMENT:
case TAG_ROSTER_ARGUMENT:
{ /* We require an associated file argument. */
const char argument_letter = argument[1];
const char *filename = &(argument[2]);
if (*filename == '\0') {
/* Try to pick it up from the next argument. */
argnum++;
if (argnum < argc) {
filename = argv[argnum];
argnum++;
}
/* Make sure the associated_value does not look
* like the next argument.
*/
if ((*filename == '\0') || (*filename == '-')) {
fprintf(GlobalState.logfile,
"Usage: -%c filename\n",
argument_letter);
exit(1);
}
}
else {
argnum++;
}
process_argument(argument[1], filename);
}
break;
/* Arguments with a required following value. */
case ECO_OUTPUT_LEVEL_ARGUMENT:
case GAMES_PER_FILE_ARGUMENT:
case LINE_WIDTH_ARGUMENT:
case MOVE_BOUNDS_ARGUMENT:
case PLY_BOUNDS_ARGUMENT:
{ /* We require an associated argument. */
const char argument_letter = argument[1];
const char *associated_value = &(argument[2]);
if (*associated_value == '\0') {
/* Try to pick it up from the next argument. */
argnum++;
if (argnum < argc) {
associated_value = argv[argnum];
argnum++;
}
/* Make sure the associated_value does not look
* like the next argument.
*/
if ((*associated_value == '\0') ||
(*associated_value == '-')) {
fprintf(GlobalState.logfile,
"Usage: -%c value\n",
argument_letter);
exit(1);
}
}
else {
argnum++;
}
process_argument(argument[1], associated_value);
}
break;
case OUTPUT_FEN_STRING_ARGUMENT:
/* May be following by an optional argument immediately after
* the argument letter.
*/
process_argument(argument[1], &argument[2]);
argnum++;
break;
/* Argument that require different treatment because they
* are present on the command line rather than an argsfile.
*/
case TAGS_ARGUMENT:
case MOVES_ARGUMENT:
case POSITIONS_ARGUMENT:
case ENDINGS_ARGUMENT:
case ENDINGS_COLOURED_ARGUMENT:
{
/* From the command line, we require an
* associated file argument.
* Check this here, as it is not the case
* when reading arguments from an argument file.
*/
const char *filename = &(argument[2]);
const char argument_letter = argument[1];
if (*filename == '\0') {
/* Try to pick it up from the next argument. */
argnum++;
if (argnum < argc) {
filename = argv[argnum];
argnum++;
}
/* Make sure the filename does not look
* like the next argument.
*/
if ((*filename == '\0') || (*filename == '-')) {
fprintf(GlobalState.logfile,
"Usage: -%cfilename or -%c filename\n",
argument_letter, argument_letter);
exit(1);
}
}
else {
argnum++;
}
process_argument(argument_letter, filename);
}
break;
case HASHCODE_MATCH_ARGUMENT:
process_argument(argument[1], &argument[2]);
argnum++;
break;
default:
fprintf(GlobalState.logfile,
"Unknown flag %s. Use -%c for usage details.\n",
argument, HELP_ARGUMENT);
exit(1);
break;
}
}
else {
/* Should be a file name containing games. */
add_filename_to_source_list(argument, NORMALFILE);
argnum++;
}
}
/* Make some adjustments to other settings if JSON output is required. */
if (GlobalState.json_format) {
if (GlobalState.output_format != EPD &&
GlobalState.output_format != CM &&
GlobalState.ECO_level == DONT_DIVIDE) {
GlobalState.keep_comments = FALSE;
GlobalState.keep_variations = FALSE;
GlobalState.keep_results = FALSE;
}
else {
fprintf(GlobalState.logfile, "JSON output is not currently supported with -E, -Wepd or -Wcm\n");
GlobalState.json_format = FALSE;
}
}
/* Prepare the hash tables for duplicate detection. */
init_duplicate_hash_table();
if (GlobalState.add_ECO) {
/* Read in a list of ECO lines in order to classify the games. */
if (open_eco_file(GlobalState.eco_file)) {
/* Indicate that the ECO file is currently being parsed. */
GlobalState.parsing_ECO_file = TRUE;
yyparse(ECOFILE);
reset_line_number();
GlobalState.parsing_ECO_file = FALSE;
}
else {
fprintf(GlobalState.logfile, "Unable to open the ECO file %s.\n",
GlobalState.eco_file);
exit(1);
}
}
/* Open up the first file as the source of input. */
if (!open_first_file()) {
exit(1);
}
yyparse(GlobalState.current_file_type);
/* @@@ I would prefer this to be somewhere else. */
if (GlobalState.json_format &&
!GlobalState.check_only &&
GlobalState.num_games_matched > 0) {
fputs("\n]\n", GlobalState.outputfile);
}
/* Remove any temporary files. */
clear_duplicate_hash_table();
if (GlobalState.verbosity > 1) {
fprintf(GlobalState.logfile, "%lu game%s matched out of %lu.\n",
GlobalState.num_games_matched,
GlobalState.num_games_matched == 1 ? "" : "s",
GlobalState.num_games_processed);
}
if ((GlobalState.logfile != stderr) && (GlobalState.logfile != NULL)) {
(void) fclose(GlobalState.logfile);
}
return 0;
}

2467
pgn-extract/map.c Normal file

File diff suppressed because it is too large Load Diff

48
pgn-extract/map.h Normal file
View File

@@ -0,0 +1,48 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef MAP_H
#define MAP_H
void init_hashtab(void);
Boolean determine_move_details(Colour colour,Move *move_details, Board *board);
HashCode hash_lookup(Col col, Rank rank, Piece piece, Colour colour);
void make_move(MoveClass class, Col from_col, Rank from_rank, Col to_col, Rank to_rank,
Piece piece, Colour colour,Board *board);
CheckStatus king_is_in_check(const Board *board,Colour king_colour);
MovePair *find_pawn_moves(Col from_col, Rank from_rank, Col to_col,Rank to_rank,
Colour colour, const Board *board);
MovePair *find_knight_moves(Col to_col,Rank to_rank, Colour colour, const Board *board);
MovePair *find_bishop_moves(Col to_col,Rank to_rank, Colour colour, const Board *board);
MovePair *find_rook_moves(Col to_col,Rank to_rank, Colour colour, const Board *board);
MovePair *find_queen_moves(Col to_col,Rank to_rank, Colour colour, const Board *board);
MovePair *find_king_moves(Col to_col,Rank to_rank, Colour colour, const Board *board);
MovePair *exclude_checks(Piece piece, Colour colour,MovePair *possibles,
const Board *board);
void free_move_pair_list(MovePair *move_list);
Boolean king_is_in_checkmate(Colour colour,Board *board);
Col find_castling_king_col(Colour colour, const Board *board);
Col find_castling_rook_col(Colour colour, const Board *board, MoveClass castling);
MovePair *find_all_moves(const Board *board, Colour colour);
Boolean at_least_one_move(const Board *board, Colour colour);
#endif // MAP_H

786
pgn-extract/moves.c Normal file
View File

@@ -0,0 +1,786 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/***
* These routines are concerned with gathering moves of
* the various sorts of variations specified by the -v
* and -x flags. In the former case, there are also functions
* for checking the moves of a game against the variation
* lists that are wanted. Checking of the variations specified
* by the -x flag is handled elsewhere by apply_move_list().
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bool.h"
#include "mymalloc.h"
#include "lines.h"
#include "defs.h"
#include "typedef.h"
#include "map.h"
#include "lists.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
#include "moves.h"
#include "apply.h"
#include "decode.h"
#include "fenmatcher.h"
/* Define a character that can be used in the variations file to
* mean that we don't mind what move was played at this point.
* So:
* * b6
* means look for all games in which Black playes 1...b6, regardless
* of White's first move.
*/
#define ANY_MOVE '*'
/* Define a character that can be used in the variations file to
* mean that we do not wish to match a particular move.
* So:
* e4 c5 !Nf3
* means look for games in which Black does not play 2. Nf3 against
* the Sicilian defence.
*/
#define DISALLOWED_MOVE '!'
/* Hold details of a single move within a variation. */
typedef struct {
/* Characters of the move.
* Alternative notations for the same move are separated by
* a non-move character, e.g.:
* cxd|cxd4|c5xd4
* could all be alternatives for the same basic pawn capture.
*/
char *move;
/* If we are interested in matching the moves in any order,
* then we need to record whether or not the current move has
* been matched or not.
*/
Boolean matched;
} variant_move;
/* Hold details of a single variation, with a pointer to
* an alternative variation.
*/
typedef struct variation_list {
/* The list of moves. */
variant_move *moves;
/* Keep a count of how many ANY_MOVE moves there are in the move
* list for each colour. If these are non-zero then one is used
* when a match fails when looking for permutations.
*/
unsigned num_white_any_moves;
unsigned num_black_any_moves;
/* Keep a count of how many DISALLOWED_MOVE moves there are in the move
* list for each colour. If these are non-zero then the game
* must be searched for them when looking for permutations before
* the full search is made.
*/
unsigned num_white_disallowed_moves;
unsigned num_black_disallowed_moves;
/* How many half-moves in the variation? */
unsigned length;
struct variation_list *next;
} variation_list;
/* The head of the variations-of-interest list. */
static variation_list *games_to_keep = NULL;
static Boolean textual_variation_match(const char *variation_move,
const unsigned char *actual_move);
/*** Functions concerned with reading details of the variations
*** of interest.
***/
/* Remove any move number prefix from str.
* Return NULL if there is no move (only number)
* otherwise return the head of the move portion.
*/
static char *
strip_move_number(char *str)
{
while (isdigit((int) *str)) {
str++;
}
while (*str == '.') {
str++;
}
if (*str != '\0') {
return str;
}
else {
return (char *) NULL;
}
}
/* Define values for malloc/realloc allocation. */
#define INIT_MOVE_NUMBER 10
#define MOVE_INCREMENT 5
/* Break up a single line of moves into a list of moves
* comprising a variation.
*/
static variation_list *
compose_variation(char *line)
{
variation_list *variation;
variant_move *move_list;
/* Keep track of the number of moves extracted from line. */
unsigned num_moves = 0;
unsigned max_moves = 0;
char *move;
variation = (variation_list *) malloc_or_die(sizeof (variation_list));
/* We don't yet know how many ANY_MOVEs or DISALLOWED_MOVES there
* will be in this variation.
*/
variation->num_white_any_moves = 0;
variation->num_black_any_moves = 0;
variation->num_white_disallowed_moves = 0;
variation->num_black_disallowed_moves = 0;
/* Allocate an initial number of pointers for the moves of the variation. */
move_list = (variant_move *) malloc_or_die(INIT_MOVE_NUMBER *
sizeof (*move_list));
max_moves = INIT_MOVE_NUMBER;
/* Find the first move. */
move = strtok(line, " ");
while (move != NULL) {
if ((move = strip_move_number(move)) == NULL) {
/* Only a move number. */
}
else {
/* See if we need some more space. */
if (num_moves == max_moves) {
move_list = (variant_move *) realloc_or_die((void *) move_list,
(max_moves + MOVE_INCREMENT) * sizeof (*move_list));
if (move_list == NULL) {
/* Catastrophic failure. */
free((void *) variation);
return NULL;
}
else {
max_moves += MOVE_INCREMENT;
}
}
/* Keep the move and initialise the matched field for
* when we start matching games.
*/
move_list[num_moves].move = move;
move_list[num_moves].matched = FALSE;
/* Keep track of moves that will match anything. */
if (*move == ANY_MOVE) {
/* Odd numbered half-moves in the variant list are Black. */
if (num_moves & 0x01) {
variation->num_black_any_moves++;
}
else {
variation->num_white_any_moves++;
}
/* Beware of the potential for false matches. */
if (strlen(move) > 1) {
fprintf(GlobalState.logfile,
"Warning: %c in %s should not be followed by additional move text.\n",
*move, move);
fprintf(GlobalState.logfile, "It could give false matches.\n");
}
}
else if (*move == DISALLOWED_MOVE) {
/* Odd numbered half-moves in the variant list are Black. */
if (num_moves & 0x01) {
variation->num_black_disallowed_moves++;
}
else {
variation->num_white_disallowed_moves++;
}
}
else {
/* Unadorned move. */
}
num_moves++;
}
move = strtok((char *) NULL, " ");
}
variation->moves = move_list;
variation->length = num_moves;
variation->next = NULL;
return variation;
}
/* Read each line of input and decompose it into a variation
* to be placed in the games_to_keep list.
*/
void
add_textual_variations_from_file(FILE *fpin)
{
char *line;
while ((line = read_line(fpin)) != NULL) {
add_textual_variation_from_line(line);
}
}
/* Add the text of the given line to the list of games_to_keep.
*/
void
add_textual_variation_from_line(char *line)
{
if (non_blank_line(line)) {
variation_list *next_variation = compose_variation(line);
if (next_variation != NULL) {
next_variation->next = games_to_keep;
games_to_keep = next_variation;
}
}
}
/*** Functions concerned with reading details of the positional
*** variations of interest.
***/
/* Break up a single line of moves into a list of moves
* comprising a positional variation.
* In doing so, set GlobalState.depth_of_positional_search
* if this variation is longer than the default.
*/
static Move *
compose_positional_variation(char *line)
{
char *move;
/* Build a linked list of the moves of the variation. */
Move *head = NULL, *tail = NULL;
Boolean Ok = TRUE;
/* Keep track of the ply depth. */
unsigned depth = 0;
move = strtok(line, " ");
while (Ok && (move != NULL) && (*move != '*')) {
if ((move = strip_move_number(move)) == NULL) {
/* Only a move number. */
}
else {
Move *next = decode_move((unsigned char *) move);
if (next == NULL) {
fprintf(GlobalState.logfile, "Failed to identify %s\n", move);
Ok = FALSE;
}
else {
/* Chain it on to the list. */
if (tail == NULL) {
head = next;
tail = next;
}
else {
tail->next = next;
tail = next;
}
next->next = NULL;
}
depth++;
}
/* Pick up the next likely move. */
move = strtok(NULL, " ");
}
if (Ok) {
/* Determine whether the depth of this variation exceeds
* the current default.
* Depth is counted in ply.
* Add some extras, in order to catch transpositions.
*/
depth += 8;
if (depth > GlobalState.depth_of_positional_search) {
GlobalState.depth_of_positional_search = depth;
}
}
else {
if (head != NULL) {
free_move_list(head);
}
head = NULL;
}
return head;
}
/* Read each line of input and decompose it into a positional variation
* to be placed in the list of required hash values.
*/
void
add_positional_variations_from_file(FILE *fpin)
{
char *line;
while ((line = read_line(fpin)) != NULL) {
add_positional_variation_from_line(line);
}
}
void
add_positional_variation_from_line(char *line)
{
if (non_blank_line(line)) {
Move *next_variation = compose_positional_variation(line);
if (next_variation != NULL) {
/* We need a NULL fen string, because this is from
* the initial position.
*/
store_hash_value(next_variation, (const char *) NULL);
free_move_list(next_variation);
/* We need to know globally that positional variations
* are of interest.
*/
GlobalState.positional_variations = TRUE;
}
}
}
/* Treat fen_string as being a position to be matched.
*/
void
add_fen_positional_match(const char *fen_string)
{
store_hash_value((Move *) NULL, fen_string);
GlobalState.positional_variations = TRUE;
}
/* Treat fen_pattern as being a position to be matched.
*/
void
add_fen_pattern_match(const char *fen_pattern, Boolean add_reverse, const char *label)
{
add_fen_pattern(fen_pattern, add_reverse, label);
GlobalState.positional_variations = TRUE;
}
/* Roughly define a move character for the purposes of textual
* matching.
*/
static Boolean
move_char(char c)
{
return (Boolean) isalpha((int) c) || isdigit((int) c) || (c == '-');
}
/* Return TRUE if there is a match for actual_move in variation_move.
* A match means that the string in actual_move is found surrounded
* by non-move characters in variation_move. For instance,
* variation_move == "Nc6|Nf3|f3" would match
* actual_move == "f3" but not actual_move == "c6".
*/
static Boolean
textual_variation_match(const char *variation_move, const unsigned char *actual_move)
{
const char *match_point;
Boolean found = FALSE;
for (match_point = variation_move; !found && (match_point != NULL);) {
/* Try for a match from where we are. */
match_point = strstr(match_point, (const char *) actual_move);
if (match_point != NULL) {
/* A possible match. Make sure that the match point
* is surrounded by non-move characters so as to be sure
* that we haven't picked up part way through a variation string.
* Assume success.
*/
found = TRUE;
if (match_point != variation_move) {
if (move_char(match_point[-1])) {
found = FALSE;
}
}
if (move_char(match_point[strlen((const char *) actual_move)])) {
found = FALSE;
}
if (!found) {
/* Move on the match point and try again. */
while (move_char(*match_point)) {
match_point++;
}
}
}
}
return found;
}
/*** Functions concerned with matching the moves of the current game
*** against the variations of interest.
***/
/* Do the moves of the current game match the given variation?
* Go for a straight 1-1 match in the ordering, without considering
* permutations.
* Return TRUE if so, FALSE otherwise.
*/
static Boolean
straight_match(Move *current_game_head, variation_list variation)
{
variant_move *moves_of_the_variation;
/* Which is the next move that we wish to match. */
Move *next_move;
unsigned move_index = 0;
/* Assume that it matches. */
Boolean matches = TRUE;
/* Access the head of the current game. */
next_move = current_game_head;
/* Go for a straight move-by-move match in the order in which
* the variation is listed.
* Point at the head of the moves list.
*/
moves_of_the_variation = variation.moves;
move_index = 0;
while (matches && (next_move != NULL) && (move_index < variation.length)) {
Boolean this_move_matches;
if (*(moves_of_the_variation[move_index].move) == ANY_MOVE) {
/* Still matching as we don't care what the actual move is. */
}
else {
this_move_matches =
textual_variation_match(moves_of_the_variation[move_index].move,
next_move->move);
if (this_move_matches) {
/* We found a match, check that it isn't disallowed. */
if (*moves_of_the_variation[move_index].move == DISALLOWED_MOVE) {
/* This move is disallowed and implies failure. */
matches = FALSE;
}
}
else {
if (*moves_of_the_variation[move_index].move != DISALLOWED_MOVE) {
/* No match found for this move. */
matches = FALSE;
}
else {
/* This is ok, because we didn't want a match. */
}
}
}
/* If we are still matching, go on to the next move. */
if (matches) {
move_index++;
next_move = next_move->next;
}
}
/* The game could be shorter than the variation, so don't rely
* on the fact that matches is still true.
*/
matches = (move_index == variation.length);
return matches;
}
/* Do the moves of the current game match the given variation?
* Try all possible orderings for the moves, within the
* constraint of proper WHITE/BLACK moves.
* The parameter variation is passed as a copy because we modify
* the num_ fields within it.
* Note that there is a possibility of a false match in this
* function if a variant move is specified in a form such as:
* *|c4
* This is because the num_ field is set from this on the basis of the
* ANY_MOVE character at the start. However, this could also match a
* normal move with its c4 component. If it is used for the latter
* purpose then it should not count as an any_ move. There is a warning
* issued about this when variations are read in.
* Return TRUE if we match, FALSE otherwise.
*
* The DISALLOWED_MOVE presents some problems with permutation matches
* because an ANY_MOVE could match an otherwise disallowed move. The
* approach that has been taken is to cause matching of a single disallowed
* move to result in complete failure of the current match.
*/
static Boolean
permutation_match(Move *current_game_head, variation_list variation)
{
variant_move *moves_of_the_variation;
/* Which is the next move that we wish to match? */
Move *next_move;
unsigned variant_index = 0;
/* Assume that it matches. */
Boolean matches = TRUE;
/* How many moves have we matched?
* When this reaches variation.length we have a full match.
*/
unsigned matched_moves = 0;
Boolean white_to_move = TRUE;
moves_of_the_variation = variation.moves;
/* Clear all of the matched fields of the variation. */
for (variant_index = 0; variant_index < variation.length; variant_index++) {
moves_of_the_variation[variant_index].matched = FALSE;
}
/* Access the head of the current game. */
next_move = current_game_head;
/*** Stage One.
* The first task is to ensure that there are no DISALLOWED_MOVEs in
* the current game.
*/
if ((variation.num_white_disallowed_moves > 0) ||
(variation.num_black_disallowed_moves > 0)) {
unsigned tested_moves = 0;
Boolean disallowed_move_found = FALSE;
/* Keep going as long as we still have not found a diallowed move,
* we haven't matched the whole variation, and we haven't reached the end of
* the game.
*/
while ((!disallowed_move_found) && (tested_moves < variation.length) &&
(next_move != NULL)) {
/* We want to see if next_move is a disallowed move of the variation. */
if (white_to_move) {
/* White; start with the first move. */
variant_index = 0;
}
else {
/* For a Black move, start at the second half-move in the list, if any. */
variant_index = 1;
}
/* Try each move of the variation in turn, until a match is found. */
while ((!disallowed_move_found) && (variant_index < variation.length)) {
if ((*moves_of_the_variation[variant_index].move ==
DISALLOWED_MOVE) &&
(textual_variation_match(
moves_of_the_variation[variant_index].move, next_move->move))) {
/* Found one. */
disallowed_move_found = TRUE;
}
if (!disallowed_move_found) {
/* Move on to the next available move -- 2 half moves along. */
variant_index += 2;
}
}
if (!disallowed_move_found) {
/* Ok so far, so move on. */
tested_moves++;
white_to_move = !white_to_move;
next_move = next_move->next;
}
}
if (disallowed_move_found) {
/* This rules out the whole match. */
matches = FALSE;
}
else {
/* In effect, each DISALLOWED_MOVE now becomes an ANY_MOVE. */
for (variant_index = 0; variant_index < variation.length; variant_index++) {
if (*moves_of_the_variation[variant_index].move == DISALLOWED_MOVE) {
moves_of_the_variation[variant_index].matched = TRUE;
if ((variant_index & 1) == 0) {
variation.num_white_any_moves++;
}
else {
variation.num_black_any_moves++;
}
}
}
}
}
/*** Stage Two.
* Having eliminated moves which have been disallowed, try permutations
* of the variation against the moves of the current game.
*/
/* Access the head of the current game. */
next_move = current_game_head;
white_to_move = TRUE;
/* Keep going as long as we still have matches, we haven't
* matched the whole variation, and we haven't reached the end of
* the game.
*/
while (matches && (matched_moves < variation.length) && (next_move != NULL)) {
/* Assume failure. */
matches = FALSE;
/* We want to find next_move in an unmatched move of the variation. */
if (white_to_move) {
/* Start with the first move. */
variant_index = 0;
}
else {
/* For a Black move, start at the second half-move in the list, if any. */
variant_index = 1;
}
/* Try each move of the variation in turn, until a match is found. */
while ((!matches) && (variant_index < variation.length)) {
if (moves_of_the_variation[variant_index].matched) {
/* We can't try this. */
}
else {
Boolean this_move_matches = textual_variation_match(
moves_of_the_variation[variant_index].move,
next_move->move);
if (this_move_matches) {
/* Found it. */
moves_of_the_variation[variant_index].matched = TRUE;
matches = TRUE;
}
}
if (!matches) {
/* Move on to the next available move -- 2 half moves along. */
variant_index += 2;
}
}
/* See if we made a straight match. */
if (!matches) {
/* See if we have some ANY_MOVEs available. */
if (white_to_move && (variation.num_white_any_moves > 0)) {
matches = TRUE;
variation.num_white_any_moves--;
}
else if (!white_to_move && (variation.num_black_any_moves > 0)) {
matches = TRUE;
variation.num_black_any_moves--;
}
else {
/* No slack. */
}
}
/* We have tried everything, did we succeed? */
if (matches) {
/* Yes, so move on. */
matched_moves++;
next_move = next_move->next;
white_to_move = !white_to_move;
}
}
if (matches) {
/* Ensure that we completed the variation. */
matches = matched_moves == (variation.length);
}
return matches;
}
/* Determine whether or not the current game is wanted.
* It will be if we are either not looking for checkmate-only
* games, or if we are and the games does end in checkmate.
*/
Boolean
check_for_only_checkmate(const Game *game_details)
{
if (GlobalState.match_only_checkmate) {
const Move *moves = game_details->moves;
/* Check that the final move is checkmate. */
while (moves != NULL && moves->check_status != CHECKMATE) {
moves = moves->next;
}
if (moves == NULL) {
return FALSE;
}
else {
return TRUE;
}
}
else {
/* No restriction to a checkmate game. */
return TRUE;
}
}
/* Determine whether or not the current game is wanted.
* It will be if we are either not looking for stalemate-only
* games, or if we are and the games does end in stalemate.
*/
Boolean
check_for_only_stalemate(const Board *board, const Move *moves)
{
if (GlobalState.match_only_stalemate) {
return is_stalemate(board, moves);
}
else {
/* No restriction to a stalemate game. */
return TRUE;
}
}
/*
* Determine whether the final position on the given board
* is stalemate or not.
*/
Boolean
is_stalemate(const Board *board, const Move *moves)
{
if (moves != NULL) {
/* Check that the final move is not check or checkmate. */
const Move *move = moves;
while (move->next != NULL) {
move = move->next;
}
if (move->check_status != NOCHECK) {
/* Cannot be stalemate. */
return FALSE;
}
}
return !at_least_one_move(board, board->to_move);
}
/* Determine whether or not the current game is wanted.
* It will be if it matches one of the current variations
* and its tag details match those that we are interested in.
*/
Boolean
check_textual_variations(const Game *game_details)
{
Boolean wanted = FALSE;
variation_list *variation;
if (games_to_keep != NULL) {
for (variation = games_to_keep; (variation != NULL) && !wanted;
variation = variation->next) {
if (GlobalState.match_permutations) {
wanted = permutation_match(game_details->moves, *variation);
}
else {
wanted = straight_match(game_details->moves, *variation);
}
}
}
else {
/* There are no variations, assume that selection is done
* on the basis of the Details.
*/
wanted = TRUE;
}
return wanted;
}
/* Determine whether the number of ply in this game
* is within the bounds of what we want.
*/
Boolean
check_move_bounds(unsigned plycount)
{
if (GlobalState.check_move_bounds) {
return (GlobalState.lower_move_bound <= plycount) &&
(plycount <= GlobalState.upper_move_bound);
}
else {
// No restriction.
return TRUE;
}
}

38
pgn-extract/moves.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef MOVES_H
#define MOVES_H
void add_positional_variations_from_file(FILE *fpin);
void add_positional_variation_from_line(char *line);
void add_textual_variations_from_file(FILE *fpin);
void add_textual_variation_from_line(char *line);
Boolean check_textual_variations(const Game *game_details);
Boolean check_move_bounds(unsigned plycount);
void add_fen_positional_match(const char *fen_string);
void add_fen_pattern_match(const char *fen_pattern, Boolean add_reverse, const char *label);
Boolean check_for_only_checkmate(const Game *game_details);
Boolean check_for_only_stalemate(const Board *board, const Move *moves);
Boolean is_stalemate(const Board *board, const Move *moves);
#endif // MOVES_H

52
pgn-extract/mymalloc.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include "mymalloc.h"
/* Allocate the required space or abort the program. */
void *
malloc_or_die(size_t nbytes)
{
void *result;
result = malloc(nbytes);
if (result == NULL) {
perror("malloc or die");
abort();
}
return result;
}
/* Allocate the required space or abort the program. */
void *
realloc_or_die(void *space, size_t nbytes)
{
void *result;
result = realloc(space, nbytes);
if (result == NULL) {
perror("realloc or die");
abort();
}
return result;
}

30
pgn-extract/mymalloc.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef MYMALLOC_H
#define MYMALLOC_H
void *malloc_or_die(size_t nbytes);
void *realloc_or_die(void *space,size_t nbytes);
char *copy_string(const char *str);
#endif // MYMALLOC_H

1797
pgn-extract/output.c Normal file

File diff suppressed because it is too large Load Diff

38
pgn-extract/output.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef OUTPUT_H
#define OUTPUT_H
void format_game(Game *current_game,FILE *outputfile);
void print_str(FILE *fp, const char *str);
void terminate_line(FILE *fp);
OutputFormat which_output_format(const char *arg);
const char *output_file_suffix(OutputFormat format);
void add_to_output_tag_order(TagName tag);
void set_output_line_length(unsigned max);
void add_plycount(const Game *game);
void add_total_plycount(const Game *game, Boolean count_variations);
/* Provide enough static space to build FEN string. */
#define FEN_SPACE 100
#endif // OUTPUT_H

View File

@@ -0,0 +1,45 @@
.TH PGN-EXTRACT 1 "May 19, 2013"
.SH NAME
pgn-extract - a Portable Game Notation (PGN) extractor
.SH SYNOPSIS
.B pgn-extract
[flags] file.pgn [file.pgn ...]
.SH DESCRIPTION
.B pgn-extract
is a free, open-source program pgn-extract, which is designed to
support the processing, searching and extraction of chess games from
files written in PGN format. There are several ways to specify the
criteria on which to extract: textual move sequences, the position
reached after a sequence of moves, information in the tag fields, and
material balance in the ending. Full ANSI C source and a 32-bit
Windows binary for the program are available under the terms of the
GNU General Public License. The program includes a semantic analyser
which will report errors in game scores and it is also able to detect
duplicate games found in one or more of its input files.
The range of input move formats accepted is fairly wide and includes
recognition of lower-case piece letters for English and upper-case
piece letters for Dutch and German. The default output is in English
Standard Algebraic Notation (SAN), although there is some support for
output in different notations.
Extracted games may be written out either including or excluding
comments, NAGs, and variations. Games may be given ECO classifications
derived from the accompanying file eco.pgn, or a customised version
provided by the user.
Plus, lots of other useful features that have gradually found their
way into what was once a relatively simple program!
.SH OPTIONS
Run
.B pgn-extract -h
to get all the options.
A complete description of each option can be found in
.B /usr/share/doc/pgn-extract/help.html
.SH AUTHOR
pgn-extract was written by David J. Barnes <d.j.barnes@kent.ac.uk>.
This manual page was written by Peter van Rossum <petervr@debian.org>
and Vincent Legout <vlegout@debian.org>, for the Debian GNU/Linux
system.

125
pgn-extract/pgn-extract.xml Normal file
View File

@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<rss version="2.0">
<channel>
<title>Home Page for pgn-extract</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/</link>
<description>A Portable Game Notation (PGN) manipulator</description>
<item>
<title>Version 22-11</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-11.tgz</link>
<description>C source code for version 22-11.
Windows binary available from the home page.
A couple of bug fixes associated with position matching via -z.
New options --firstgame, --gamelimit, --seventyfive and --repetition5.
Regular expression matches via -t.
</description>
<guid isPermaLink="false">pgn-extract-22-11-announce</guid>
<pubDate>15 August 2022 21:00:00 GMT</pubDate>
</item>
<item>
<title>Version 22-07</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-07.tgz</link>
<description>C source code for version 22-07.
Windows binary available from the home page.
This is largely a bug fix release to fix failure to NULL a freed pointer.
In addition, relational operators may now be used to match
any wholly numeric tag values via the -t flag.
</description>
<guid isPermaLink="false">pgn-extract-22-07-announce</guid>
<pubDate>03 May 2022 22:00:00 GMT</pubDate>
</item>
<item>
<title>Version 22-05</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-05.tgz</link>
<description>C source code for version 22-05.
Windows binary available from the home page.
This is largely a bug fix release.
</description>
<guid isPermaLink="false">pgn-extract-22-05-announce</guid>
<pubDate>23 Feb 2022 21:00:00 GMT</pubDate>
</item>
<item>
<title>Version 21-08</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-21-08.tgz</link>
<description>C source code for version 21-08. Windows 64-bit and 32-bit
binaries available from the home page.
This is a catch-up release for the end of the year. It adds a
de-tagging option, and extended
matching of TimeControl to include the formats of sudden death and sandclock. </description>
<guid isPermaLink="false">pgn-extract-21-08-announce</guid>
<pubDate>28 Dec 2021 17:00:00 GMT</pubDate>
</item>
<item>
<title>Version 21-02</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-21-02.tgz</link>
<description>C source code for version 21-02. win32 binary available from
the home page.
This version is mainly a bug-fix release for the --fixtagstrings option but
it also adds the --linenumbers option.
</description>
<guid isPermaLink="false">pgn-extract-21-02-announce</guid>
<pubDate>27 Jan 2021 11:45:00 GMT</pubDate>
</item>
<item>
<title>Version 20-06</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-20-06.tgz</link>
<description>C source code for version 20-06. win32 binary available from
the home page.
This version is mainly an end-of-year release to catch up on a few additions
since version 20-03.
Date matches extended to match on month and day as well as year and a few more
command-line options: --fixtagstrings attempts to fix common bad string formats
in tag strings; and --wtm/--btm add the requirement for white-to-move/black-to-move
in matches.
</description>
<guid isPermaLink="false">pgn-extract-20-06-announce</guid>
<pubDate>18 Dec 2020 21:00:00 GMT</pubDate>
</item>
<item>
<title>Version 20-03</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-20-03.tgz</link>
<description>C source code for version 20-03. win32 binary available from
the home page.
This version contains a few bug fixes and adds --startply, --fenpattern and --material
command-line options.
There is also limited relational matching for the TimeControl tag.
</description>
<guid isPermaLink="false">pgn-extract-20-03-announce</guid>
<pubDate>25 July 2020 21:00:00 GMT</pubDate>
</item>
<item>
<title>Version 19-04</title>
<link>https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-19-04.tgz</link>
<description>C source code for version 19-04. win32 binary available from
the home page. This version fixes a memory error with some positional match
combinations and false positives with --repetition.
It also adds --xroster to suppress additional tags with -R and adds a short
man page courtesy of Vincent Legout.
</description>
<guid isPermaLink="false">pgn-extract-19-04-announce</guid>
<pubDate>23 April 2019 21:00:00 GMT</pubDate>
</item>
<item>
<title>Using pgn-extract to mine chess data</title>
<link>https://blogs.kent.ac.uk/djb/2018/10/14/data-mining-with-pgn-extract/</link>
<description>A blog post about using pgn-extract to investigate the
effect of material balances, with a particular focus on the case
of the bishop pair.
</description>
<guid isPermaLink="false">pgn-extract-data-mining</guid>
<pubDate>16 October 2018 07:45:00 GMT</pubDate>
</item>
</channel>
</rss>

520
pgn-extract/style.css Executable file
View File

@@ -0,0 +1,520 @@
/*
Design by Free CSS Templates
http://www.freecsstemplates.org
Released for free under a Creative Commons Attribution 2.5 License
*/
body {
margin: 0px 0px 0px 0px;
padding: 0;
background: #FFFFFF;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
}
h1, h2, h3 {
margin: 0;
padding: 0;
font-weight: 200;
color: #222222;
}
h1 {
font-size: 3em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.5em;
}
p, ol, ul, pre, td {
margin-top: 0px;
padding: 0px;
color: #070707;
/* color: #000000; */
font-size: 14px;
}
p, ol {
/* line-height: 180%; */
}
p {
}
ul {
margin-left: 20px;
}
table, th, td {
margin-left: 20px;
border: 1px solid black;
padding: 5px;
text-align: left;
vertical-align: middle;
}
li {
margin-left: 20px;
}
pre {
margin-left: 2em;
font-family: "Courier New", "Lucida Console", monospace;
}
strong {
}
a {
color: #5C5539;
}
a:hover {
text-decoration: none;
}
a img {
border: none;
}
img.border {
}
img.alignleft {
float: left;
}
img.alignright {
float: right;
}
img.aligncenter {
margin: 0px auto;
}
hr {
display: none;
}
/** WRAPPER */
#wrapper {
overflow: hidden;
background: #FFFFFF;
}
.container {
/* width: 1200px; */
margin: 0px auto;
}
.clearfix {
clear: both;
}
/* Header */
#header-wrapper {
overflow: hidden;
height: 150px;
}
#header {
/* width: 1200px; */
height: 150px;
margin: 0 auto;
padding: 0px 0px;
}
/* Logo */
#logo {
float: left;
width: 310px;
height: 150px;
padding: 0px 0px 0px 40px;
}
#logo h1 {
padding: 50px 0px 0px 0px;
text-transform: lowercase;
letter-spacing: -2px;
font-size: 3.6em;
}
#logo h1 a {
text-decoration: none;
color: #FFFFFF;
}
/* Menu */
#menu {
float: right;
width: 810px;
height: 80px;
padding: 20px 40px 0px 0px;
}
#menu ul {
float: right;
margin: 0;
padding: 40px 0px 0px 0px;
list-style: none;
line-height: normal;
}
#menu li {
float: left;
}
#menu a {
display: block;
margin-left: 1px;
padding: 7px 20px 7px 20px;
letter-spacing: 1px;
text-decoration: none;
text-align: center;
text-transform: uppercase;
font-family: 'Oswald', sans-serif;
font-size: 16px;
font-weight: 300;
color: #FFFFFF;
}
#menu a:hover, #menu .current_page_item a {
text-decoration: none;
background: #1B5902;
border-radius: 5px;
color: #FFFFFF;
}
/* Page */
#page-wrapper {
overflow: hidden;
}
#page {
overflow: hidden;
/* width: 1120px; */
margin: 0px auto;
padding: 20px 40px;
color: #8F8F8F;
border-top: 3px solid #A1A1A1;
}
/** CONTENT */
#wide-content {
}
#wide-content h2 {
padding: 0px 0px 20px 0px;
letter-spacing: -1px;
font-size: 36px;
color: #222222;
}
/** CONTENT */
#content {
float: right;
width: 800px;
padding: 0px 0px 0px 0px;
}
#content h2 {
padding: 0px 0px 20px 0px;
letter-spacing: -1px;
font-size: 36px;
color: #222222;
}
#content .subtitle {
padding: 0px 0px 30px 0px;
text-transform: uppercase;
font-family: 'Oswald', sans-serif;
font-size: 18px;
color: #81AFC5;
}
/** SIDEBAR */
#sidebar {
float: left;
width: 290px;
padding: 0px 0px 20px 0px;
}
#sidebar h2 {
padding: 0px 0px 30px 0px;
letter-spacing: -1px;
font-size: 2em;
}
/* Footer */
#footer {
margin: 0 auto;
}
#footer p {
text-align: center;
font-size: 12px;
color: #757575;
}
#footer a {
color: #757575;
}
/* Three Column Footer Content */
#footer-bg {
overflow: hidden;
padding: 40px 0px;
background:#E5E0DD url(images/main-bsg.png) repeat;
}
#footer-content {
color: #67C8E3;
}
#footer-content h2 {
margin: 0px;
padding: 0px 0px 30px 0px;
letter-spacing: -1px;
text-shadow: 1px 1px 0px #FFFFFF;
text-transform: uppercase;
font-size: 20px;
font-weight: 200;
color: #93776E;
}
#footer-content a {
}
#footer-content a:hover {
text-decoration: underline;
}
#column1 {
float: left;
width: 280px;
margin-right: 30px;
}
#column1 p {
line-height: 1;
}
#column2 {
float: left;
width: 280px;
margin-right: 30px;
}
#column3 {
float: left;
width: 280px;
}
#column4 {
float: right;
width: 260px;
}
/* Banner Style */
#banner-wrapper {
background: #FFFFFF;
}
#banner {
overflow: hidden;
background: #FFFFFF;
/* width: 1160px; */
margin: 20px auto 50px auto;
}
#banner h1 {
text-align: center
}
#banner .img-border {
height: 500px;
border: 20px solid #FFFFFF;
}
/* Button Style */
.button-style {
display: inline-block;
margin-top: 30px;
padding: 7px 30px;
background: #36332E;
border-radius: 5px;
}
.button-style a {
letter-spacing: 1px;
text-decoration: none;
text-transform: uppercase;
font-family: 'Oswald', sans-serif;
font-weight: 300;
font-size: 16px;
color: #FFFFFF;
}
/* List Style 1 */
ul.style1 {
margin: 0px;
padding: 0px;
list-style: none;
}
ul.style1 li {
padding: 25px 0px 15px 0px;
border-top: 1px solid #A1A1A1;
}
ul.style1 a {
text-decoration: none;
color: #FFFFFF;
}
ul.style1 a:hover {
text-decoration: underline;
color: #6B6B6B;
}
ul.style1 .first {
padding-top: 0px;
border-top: none;
}
/** LIST STYLE 3 */
ul.style3 {
margin: 0px;
padding: 0px;
list-style: none;
}
ul.style3 li {
padding: 10px 0px 10px 0px;
border-top: 1px solid #A1A1A1;
}
ul.style3 a {
text-decoration: none;
color: #949494;
}
ul.style3 a:hover {
text-decoration: underline;
}
ul.style3 .first {
padding-top: 0px;
border-top: none;
box-shadow: none;
}
ul.style3 .date {
width: 87px;
background-color: #36332E;
margin-top: 20px;
height: 24px;
line-height: 24px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
}
ul.style3 .first .date
{
margin-top: 0px;
}
/* Recent News */
#recent-news {
overflow: hidden;
width: 1120px;
margin: 0px auto;
padding: 50px 40px;
background: #36332E;
color: #8C8C8C;
}
#recent-news h2 {
padding: 0px 0px 20px 0px;
font-family: Arial, Helvetica, sans-serif;
font-size: 2.5em;
color: #EDEDED;
}
#recent-news .date {
padding: 0px 0px 10px 0px;
font-weight: bold;
font-style: normal;
color: #E3E3E3;
}
#recent-news p {
font-style: italic;
}
#recent-news a {
font-style: normal;
color: #B8B8B8;
}
#recent-news #rbox1 {
float: left;
width: 250px;
margin-right: 40px;
}
#recent-news #rbox2 {
float: left;
width: 250px;
margin-right: 40px;
}
#recent-news #rbox3 {
float: left;
width: 250px;
}
#recent-news #rbox4 {
float: right;
width: 250px;
}
/* Button Style */
.button-style1 {
margin-top: 30px;
}
.button-style1 a {
padding: 10px 25px;
background: #EBB462;
border-radius: 5px;
text-decoration: none;
text-shadow: 1px 1px 0px #FCE3BB;
color: #36332E !important;
}

267
pgn-extract/taglines.c Normal file
View File

@@ -0,0 +1,267 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#include <stdio.h>
#include <stdlib.h>
#include "bool.h"
#include "defs.h"
#include "typedef.h"
#include "tokens.h"
#include "taglist.h"
#include "lex.h"
#include "lines.h"
#include "lists.h"
#include "moves.h"
#include "output.h"
#include "taglines.h"
static FILE *yyin = NULL;
/* Read the list of extraction criteria from TagFile.
* This doesn't use the normal lexical analyser before the
* PGN files are processed but circumvents next_token by
* calling get_tag() and get_string. This allows it to detect
* EOF before yywrap() is called.
* Be careful to leave lex in the right state.
*/
void
read_tag_file(const char *TagFile)
{
yyin = fopen(TagFile, "r");
if (yyin != NULL) {
Boolean keep_reading = TRUE;
while (keep_reading) {
char *line = next_input_line(yyin);
if (line != NULL) {
keep_reading = process_tag_line(TagFile, line);
}
else {
keep_reading = FALSE;
}
}
(void) fclose(yyin);
/* Call yywrap in order to set up for the next (first) input file. */
(void) yywrap();
yyin = NULL;
}
else {
fprintf(GlobalState.logfile,
"Unable to open %s for reading.\n", TagFile);
exit(1);
}
}
/* Read the contents of a file that lists the
* required output ordering for tags.
*/
void
read_tag_roster_file(const char *RosterFile)
{
Boolean keep_reading = TRUE;
yyin = must_open_file(RosterFile, "r");
while (keep_reading) {
char *line = next_input_line(yyin);
if (line != NULL) {
keep_reading = process_roster_line(line);
}
else {
keep_reading = FALSE;
}
}
(void) fclose(yyin);
/* Call yywrap in order to set up for the next (first) input file. */
(void) yywrap();
}
/* Extract a tag/value pair from the given line.
* Return TRUE if this was successful.
*/
Boolean
process_tag_line(const char *TagFile, char *line)
{
Boolean keep_reading = TRUE;
if (non_blank_line(line)) {
unsigned char *linep = (unsigned char *) line;
/* We should find a tag. */
LinePair resulting_line = gather_tag(line, linep);
TokenType tag_token;
/* Pick up where we are now. */
line = resulting_line.line;
linep = resulting_line.linep;
tag_token = resulting_line.token;
if (tag_token != NO_TOKEN) {
/* Pick up which tag it was. */
int tag_index = yylval.tag_index;
/* Allow for an optional operator. */
TagOperator operator = NONE;
/* Skip whitespace. */
while (is_character_class(*linep, WHITESPACE)) {
linep++;
}
/* Allow for an optional operator. */
if (is_character_class(*linep, OPERATOR)) {
switch (*linep) {
case '<':
linep++;
if (*linep == '=') {
linep++;
operator = LESS_THAN_OR_EQUAL_TO;
}
else if (*linep == '>') {
linep++;
operator = NOT_EQUAL_TO;
}
else {
operator = LESS_THAN;
}
break;
case '>':
linep++;
if (*linep == '=') {
linep++;
operator = GREATER_THAN_OR_EQUAL_TO;
}
else {
operator = GREATER_THAN;
}
break;
case '=':
linep++;
if (*linep == '~') {
operator = REGEX;
linep++;
}
else {
operator = EQUAL_TO;
}
break;
default:
fprintf(GlobalState.logfile,
"Internal error: unknown operator in %s\n", line);
linep++;
break;
}
/* Skip whitespace. */
while (is_character_class(*linep, WHITESPACE)) {
linep++;
}
}
if (is_character_class(*linep, DOUBLE_QUOTE)) {
/* A string, as expected. */
linep++;
resulting_line = gather_string(line, linep);
line = resulting_line.line;
linep = resulting_line.linep;
if (tag_token == TAG) {
/* Treat FEN and FENPattern tags as special cases.
* Use the position they represent to indicate
* a positional match.
*/
if (tag_index == FEN_TAG) {
add_fen_positional_match(yylval.token_string);
(void) free((void *) yylval.token_string);
}
else if (tag_index == PSEUDO_FEN_PATTERN_TAG ||
tag_index == PSEUDO_FEN_PATTERN_I_TAG) {
/* Skip whitespace. */
while (is_character_class(*linep, WHITESPACE)) {
linep++;
}
const char *label;
if(*linep != '\0') {
/* Treat the remainder of the line as a label. */
label = (const char *) linep;
}
else {
label = NULL;
}
/* Generate an inverted version as well if
* it is PSEUDO_FEN_PATTERN_I_TAG.
*/
add_fen_pattern_match(yylval.token_string,
tag_index == PSEUDO_FEN_PATTERN_I_TAG, label);
(void) free((void *) yylval.token_string);
}
else {
add_tag_to_list(tag_index, yylval.token_string, operator);
(void) free((void *) yylval.token_string);
}
}
else {
if (!GlobalState.skipping_current_game) {
fprintf(GlobalState.logfile,
"File %s: unrecognised tag name %s\n",
TagFile, line);
}
(void) free((void *) yylval.token_string);
}
}
else {
if (!GlobalState.skipping_current_game) {
fprintf(GlobalState.logfile,
"File %s: missing quoted tag string in %s at %s\n",
TagFile, line, linep);
}
}
}
else {
/* Terminate the reading, as we have run out of tags. */
keep_reading = FALSE;
}
}
return keep_reading;
}
/* Extract a tag name from the given line.
* Return TRUE if this was successful.
*/
Boolean
process_roster_line(char *line)
{
Boolean keep_reading = TRUE;
if (non_blank_line(line)) {
unsigned char *linep = (unsigned char *) line;
/* We should find a tag. */
LinePair resulting_line = gather_tag(line, linep);
TokenType tag_token;
/* Pick up where we are now. */
line = resulting_line.line;
linep = resulting_line.linep;
tag_token = resulting_line.token;
if (tag_token != NO_TOKEN) {
/* Pick up which tag it was. */
int tag_index = yylval.tag_index;
add_to_output_tag_order((TagName) tag_index);
}
else {
/* Terminate the reading, as we have run out of tags. */
keep_reading = FALSE;
}
}
return keep_reading;
}

32
pgn-extract/taglines.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
#ifndef TAGLINES_H
#define TAGLINES_H
void read_tag_file(const char *TagFile);
void read_tag_roster_file(const char *RosterFile);
Boolean process_tag_line(const char *TagFile,char *line);
Boolean process_roster_line(char *line);
#endif // TAGLINES_H

112
pgn-extract/taglist.h Normal file
View File

@@ -0,0 +1,112 @@
/*
* This file is part of pgn-extract: a Portable Game Notation (PGN) extractor.
* Copyright (C) 1994-2022 David J. Barnes
*
* pgn-extract is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pgn-extract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pgn-extract. If not, see <http://www.gnu.org/licenses/>.
*
* David J. Barnes may be contacted as d.j.barnes@kent.ac.uk
* https://www.cs.kent.ac.uk/people/staff/djb/
*/
/* Define indices for the set of pre-defined tags.
* Higher values are created dynamically as new
* tags are recognised in the source files.
*/
/* List the tags so that the strings that they represent
* would be in alphabetical order. E.g. note that EVENT_TAG and
* EVENT_DATE_TAG should be in this order because the strings are
* "Event" and "EventDate".
*/
#ifndef TAGLIST_H
#define TAGLIST_H
typedef enum {
ANNOTATOR_TAG,
BLACK_TAG,
BLACK_ELO_TAG,
BLACK_NA_TAG,
BLACK_TITLE_TAG,
BLACK_TYPE_TAG,
BLACK_USCF_TAG,
BOARD_TAG,
DATE_TAG,
ECO_TAG,
/* The PSEUDO_ELO_TAG is not a real PGN one. It is used with the -t
* argument so that it becomes possible to indicate a rating of either colour.
*/
PSEUDO_ELO_TAG,
EVENT_TAG,
EVENT_DATE_TAG,
EVENT_SPONSOR_TAG,
FEN_TAG,
/* The PSEUDO_FEN_PATTERN_TAGs are not real PGN ones. They are used with the -t
* argument so that it becomes possible to indicate a FEN-based board pattern.
* The _I version indicates that the pattern should be tried in both its
* written form and inverted for the opposite colour.
*/
PSEUDO_FEN_PATTERN_TAG,
PSEUDO_FEN_PATTERN_I_TAG,
HASHCODE_TAG,
LONG_ECO_TAG,
/* The MATCHLABEL_TAG is not a real PGN one. It is used with the -t
* argument and FENPattern pseudo tag so that it becomes possible to
* which FENPattern has been matched in a game.
*/
MATCHLABEL_TAG,
/* The MATERIAL_MATCH_TAG is not a real PGN one. It is used with the -z
* argument so that it becomes possible to indicate which player's material
* matches the first material pattern in a match.
*/
MATERIAL_MATCH_TAG,
MODE_TAG,
NIC_TAG,
OPENING_TAG,
/* The PSEUDO_PLAYER_TAG is not a real PGN one. It is used with the -t
* argument so that it becomes possible to indicate a player of either colour.
*/
PSEUDO_PLAYER_TAG,
PLY_COUNT_TAG,
/* The TOTAL_PLY_COUNT_TAG is used with the --totalplycount argument
* so record the total number of plies in a game.
*/
TOTAL_PLY_COUNT_TAG,
RESULT_TAG,
ROUND_TAG,
SECTION_TAG,
SETUP_TAG,
SITE_TAG,
STAGE_TAG,
SUB_VARIATION_TAG,
TERMINATION_TAG,
TIME_TAG,
TIME_CONTROL_TAG,
UTC_DATE_TAG,
UTC_TIME_TAG,
VARIANT_TAG,
VARIATION_TAG,
WHITE_TAG,
WHITE_ELO_TAG,
WHITE_NA_TAG,
WHITE_TITLE_TAG,
WHITE_TYPE_TAG,
WHITE_USCF_TAG,
/* The following should always be last. It should not be used
* as a tag identification.
*/
ORIGINAL_NUMBER_OF_TAGS
} TagName;
#endif // TAGLIST_H

960
pgn-extract/test/Makefile Normal file
View File

@@ -0,0 +1,960 @@
# Makefile to run a battery of tests of the basic functionality of pgn-extract.
# Copyright (C) David J. Barnes, 2013-2020
#
# Each test is run and then, where relevant, a comparison is made between
# the output files generated in the current directory and the 'oracle'
# files that exist in $(OUTPUT).
#
# Beware of case-insensitive filenames when testing flags that
# differ only in letter case. In general, double letters have been
# used for output-files generated from using upper-case flag letters.
# Customise these for different OSs.
SEP=/
RM=rm -f
CMP=cmp
# Possible Windows settings
#SEP=\\
#RM=del
#CMP=diff
PGN_EXTRACT=..$(SEP)pgn-extract
# Use for memory checking if valgrind is installed.
#PGN_EXTRACT=valgrind --dsymutil=yes ..$(SEP)pgn-extract
#PGN_EXTRACT=valgrind --dsymutil=yes --leak-check=full ..$(SEP)pgn-extract
# Location of the file of ECO classifications.
ECO_FILE=..$(SEP)eco.pgn
# Location of the input files
INPUT=infiles
# Location of the oracle output files
OUTPUT=outfiles
# Test everything.
all: no-flags-1 no-flags-2 test-7 test-append test-AA test-b test-p \
test-checkfile test-nocomments test-duplicates \
test-noduplicates test-e test-EE test-f test-FF test-h test-l \
test-LL test-checkmate test-n test-NN test-output test-PP test-r \
test-RR test-s test-SS test-t test-TT test-nounique test-v \
test-VV test-linelength test-WW test-x test-ZZ test-y test-z test-hash \
test-evaluation test-fencomments test-markmatches test-nochecks \
test-nomovenumbers test-noresults test-notags test-plylimit \
test-stalemate test-long-line test-plycount test-addhashcode \
test-selectonly test-fifty test-repetition test-promotion \
test-fixresulttags test-fuzzydepth test-setup test-stopafter \
test-skipmatching test-splitvariants test-nobadresults test-allownullmoves \
test-matchplylimit test-nestedcomments test-FENPattern test-dropply \
test-startply test-linenumbers test-seventyfive
# BEWARE: This removes all PGN files in the current directory.
# The required test PGN files are assumed to be in $(INPUT).
clean:
-$(RM) *.pgn *og.txt
# No flags:
# + No input file.
# - Input file(s): N$(SEP)A
# - Example input:
# f3 e5 g4 Qh4 0-1
# - Resulting output should be that the game input on standard input is
# formatted as PGN on standard output.
# - Expected output:
# Contents of fools-mate.pgn on standard output.
no-flags-1:
echo "test: No input file."
$(PGN_EXTRACT) --quiet < $(INPUT)$(SEP)fools-mate.txt
# No flags:
# + Single input file
# - Input file(s): fools-mate.txt
# - Resulting output should be the input formatted as PGN on standard output.
# - Expected output: Contents of fools-mate.pgn should appear on standard output.
no-flags-2:
echo "test: No flags."
$(PGN_EXTRACT) --quiet $(INPUT)$(SEP)fools-mate.txt
# -7 $(SEP) --seven
# + Input file with games having tags additional to the seven tag roster.
# - Input file(s): test-7.pgn
# - Game output should have only the tags of the seven tag roster.
# - Expected output: test-7-out.pgn
test-7:
echo "test-7:"
$(PGN_EXTRACT) -7 -otest-7-out.pgn --quiet $(INPUT)$(SEP)test-7.pgn
$(CMP) test-7-out.pgn $(OUTPUT)$(SEP)test-7-out.pgn
# -a $(SEP) --append
# + Input file containing games in any accepted format.
# - Input file(s): test-a.txt
# - Resulting output should contain two versions of the input game
# formatted in PGN. The --output command is run first to create
# a new file, then the -a version to append to that file.
# - Expected output: test-a-out.pgn
test-append:
echo "test-append:"
$(PGN_EXTRACT) --output test-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt
$(PGN_EXTRACT) -atest-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt
$(CMP) test-a-out.pgn $(OUTPUT)$(SEP)test-a-out.pgn
$(PGN_EXTRACT) --output test-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt
$(PGN_EXTRACT) --append test-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt
$(CMP) test-a-out.pgn $(OUTPUT)$(SEP)test-a-out.pgn
# -A
# + Input file containing games and a file of arguments.
# - Input file(s): fischer.pgn, petrosian.pgn, arglist.txt
# - Resulting output should be files separating the unique and
# duplicated games in the input files.
# - Expected output: test-AA-unique.pgn, test-AA-dupes.pgn
test-AA:
echo "test-AA:"
$(PGN_EXTRACT) -C -A$(INPUT)$(SEP)argslist.txt --quiet
$(CMP) test-AA-dupes.pgn $(OUTPUT)$(SEP)test-AA-dupes.pgn
$(CMP) test-AA-unique.pgn $(OUTPUT)$(SEP)test-AA-unique.pgn
# -b
# + Input file containing games of different length.
# - Input file(s): fischer.pgn
# - Resulting output: games whose number of moves is within
# the specified bounds.
#
test-b: test-bl45 test-bu45 test-bu30
# -p
# + Input file containing games of different length.
# - Input file(s): fischer.pgn
# - Resulting output: games whose number of ply is within
# the specified bounds.
#
test-p: test-pl90 test-pu90 test-pu60
# - Expected output: 45 moves or more: test-bl45-out.pgn
test-bl45:
echo "test-b:"
$(PGN_EXTRACT) -bl45 -otest-bl45-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-bl45-out.pgn $(OUTPUT)$(SEP)test-bl45-out.pgn
# - Expected output: 45 moves or less: test-bu45-out.pgn
test-bu45:
echo "test-b:"
$(PGN_EXTRACT) -bu45 -otest-bu45-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-bu45-out.pgn $(OUTPUT)$(SEP)test-bu45-out.pgn
# - Expected output: exactly 30 moves: test-b30-out.pgn
test-bu30:
echo "test-b:"
$(PGN_EXTRACT) -b30 -otest-b30-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-b30-out.pgn $(OUTPUT)$(SEP)test-b30-out.pgn
# - Expected output: 90 moves or more: test-pl90-out.pgn
test-pl90:
echo "test-p:"
$(PGN_EXTRACT) -pl90 -otest-pl90-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-pl90-out.pgn $(OUTPUT)$(SEP)test-pl90-out.pgn
# - Expected output: 90 moves or less: test-pu90-out.pgn
test-pu90:
echo "test-p:"
$(PGN_EXTRACT) -pu90 -otest-pu90-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-pu90-out.pgn $(OUTPUT)$(SEP)test-pu90-out.pgn
# - Expected output: exactly 60 moves: test-p60-out.pgn
test-pu60:
echo "test-p:"
$(PGN_EXTRACT) -p60 -otest-p60-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-p60-out.pgn $(OUTPUT)$(SEP)test-p60-out.pgn
#
# -c $(SEP) --checkfile
# + Input files containing games.
# - Input file(s): fischer.pgn, petrosian.pgn
# - Resulting output should contain matched games that do not already occur in
# the check file.
# - Expected output: test-c-out.pgn
test-checkfile:
echo "test-checkfile:"
$(PGN_EXTRACT) -c$(INPUT)$(SEP)petrosian.pgn -D -TpPetrosian -otest-c-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-c-out.pgn $(OUTPUT)$(SEP)test-c-out.pgn
$(PGN_EXTRACT) -c$(INPUT)$(SEP)clist.txt -D -TpPetrosian -otest-c-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-c-out.pgn $(OUTPUT)$(SEP)test-c-out.pgn
# -C $(SEP) --nocomments
# + Input file containing games with comments
# - Input file(s): test-C.pgn
# - Resulting output should have all comments removed.
# - Expected output: test-CC-out.pgn
test-nocomments:
echo "test-nocomments:"
$(PGN_EXTRACT) -C -otest-CC-out.pgn --quiet $(INPUT)$(SEP)test-C.pgn
$(CMP) test-CC-out.pgn $(OUTPUT)$(SEP)test-CC-out.pgn
# -d $(SEP) --duplicates
# + Input file containing games with duplicates and non-duplicates.
# - Input file(s): fischer.pgn, $(INPUT)$(SEP)petrosian.pgn
# - Resulting output should be files separating the unique and
# duplicated games in the input files.
# - Expected output: test-d-unique.pgn, test-d-dupes.pgn
test-duplicates:
echo "test-duplicates:"
$(PGN_EXTRACT) -C -dtest-d-dupes.pgn -otest-d-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-d-dupes.pgn $(OUTPUT)$(SEP)test-d-dupes.pgn
$(CMP) test-d-unique.pgn $(OUTPUT)$(SEP)test-d-unique.pgn
# -D $(SEP) --noduplicates
# + Input file containing games with duplicates and non-duplicates.
# - Input file(s): fischer.pgn, $(INPUT)$(SEP)petrosian.pgn
# - Resulting output should be a file containing the combined input
# with duplicate games removed.
# - Expected output: test-DD-unique.pgn
test-noduplicates:
echo "test-noduplicates:"
$(PGN_EXTRACT) -D -otest-DD-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-DD-unique.pgn $(OUTPUT)$(SEP)test-DD-unique.pgn
$(PGN_EXTRACT) --noduplicates -otest-DD-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-DD-unique.pgn $(OUTPUT)$(SEP)test-DD-unique.pgn
# -e
# + Input file containing games without ECO classifications.
# - Input file(s): test-e.pgn and eco.pgn in the test folder.
# - Resulting output should have ECO classification added to the tags.
# - Expected output: test-e-out.pgn
test-e:
echo "test-e:"
$(PGN_EXTRACT) -e$(ECO_FILE) -otest-e-out.pgn --quiet $(INPUT)$(SEP)test-e.pgn
$(CMP) test-e-out.pgn $(OUTPUT)$(SEP)test-e-out.pgn
# -E
# + Input file containing games.
# - Input file(s): test-ucE.pgn and eco.pgn if -e flag is used.
# - Resulting output should be separate files for each ECO classification
# at the level of the initial letter (A-E).
# NB: The test removes existing A-E files first because this option appends
# to existing files, which breaks the comparison test otherwise.
# - Expected output: A.pgn, B.pgn, E.pgn
test-EE:
echo "test-EE:"
-$(RM) [A-E].pgn
$(PGN_EXTRACT) -e$(ECO_FILE) -E1 --quiet $(INPUT)$(SEP)test-ucE.pgn
$(CMP) A.pgn $(OUTPUT)$(SEP)A.pgn
$(CMP) B.pgn $(OUTPUT)$(SEP)B.pgn
$(CMP) E.pgn $(OUTPUT)$(SEP)E.pgn
# -f
# + Input files containing games.
# - Input file(s): test-f1.pgn, test-f2.pgn, files.txt
# - Resulting output should be the combination of the input files.
# - Expected output: test-f-out.pgn
test-f:
echo "test-f:"
$(PGN_EXTRACT) --quiet -f$(INPUT)$(SEP)files.txt -otest-f-out.pgn
$(CMP) test-f-out.pgn $(OUTPUT)$(SEP)test-f-out.pgn
# -F:
# + Input file containing games without a trailing FEN comment.
# - Input file(s): test-F.pgn
# - Resulting output should have a comment at the end containing
# the FEN description of the final position.
# - Expected output: test-FF-out.pgn
test-FF:
echo "test-FF:"
$(PGN_EXTRACT) -F -otest-FF-out.pgn --quiet $(INPUT)$(SEP)test-F.pgn
$(CMP) test-FF-out.pgn $(OUTPUT)$(SEP)test-FF-out.pgn
$(PGN_EXTRACT) -Fdiagram -otest-FF-text-out.pgn --quiet $(INPUT)$(SEP)test-F-text.pgn
$(CMP) test-FF-text-out.pgn $(OUTPUT)$(SEP)test-FF-text-out.pgn
#
# -h $(SEP) -? $(SEP) --help
# + No input required.
# - Input file(s): N$(SEP)A
# - Resulting output should be a description of how to use pgn-extract
# - Expected output: N$(SEP)A
# Also:
# ..$(SEP)pgn-extract -?
# ..$(SEP)pgn-extract --help
test-h:
echo "test-h:"
-$(PGN_EXTRACT) -h
# -l
# + Input file containing games.
# - Input file(s): fischer.pgn
# - Resulting output: List of games parsed written to log.txt
# - Expected output: log.txt
test-l:
echo "test-l:"
$(PGN_EXTRACT) -llog.txt -otest-l-out.pgn $(INPUT)$(SEP)fischer.pgn
$(CMP) log.txt $(OUTPUT)$(SEP)log.txt
$(CMP) test-l-out.pgn $(OUTPUT)$(SEP)test-l-out.pgn
# -L
# + Input file containing games.
# - Input file(s): test-L1.pgn, test-L2.pgn
# - Resulting output should be that log.txt contains the combined
# logs from two runs of pgn-extract.
# - Expected output: log.txt
test-LL:
echo "test-LL:"
$(PGN_EXTRACT) -lLLog.txt -r $(INPUT)$(SEP)test-L1.pgn
$(PGN_EXTRACT) -LLLog.txt -r $(INPUT)$(SEP)test-L2.pgn
$(CMP) LLog.txt $(OUTPUT)$(SEP)LLog.txt
# -M $(SEP) --checkmate
# + Input file containing games.
# - Input file(s): test-checkmate.pgn
# - Resulting output should contain only those games that end in checkmate.
# - Expected output: test-checkmate-out.pgn
test-checkmate:
echo "test-checkmate:"
$(PGN_EXTRACT) --checkmate -otest-checkmate-out.pgn --quiet $(INPUT)$(SEP)test-checkmate.pgn
$(CMP) test-checkmate-out.pgn $(OUTPUT)$(SEP)test-checkmate-out.pgn
# -n
# + Input file containing games.
# - Input file(s): petrosian.pgn
# - Resulting output should be separate files containing matched
# and non-matched games.
# - Expected output: test-n-matched.pgn, test-n-unmatched.pgn
test-n:
echo "test-n:"
$(PGN_EXTRACT) -TpFischer -otest-n-matched.pgn -ntest-n-unmatched.pgn --quiet $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-n-matched.pgn $(OUTPUT)$(SEP)test-n-matched.pgn
$(CMP) test-n-unmatched.pgn $(OUTPUT)$(SEP)test-n-unmatched.pgn
# -N $(SEP) --nonags
# + Input file containing games with NAGs.
# - Input file(s): test-N.pgn
# - Resulting output should have all NAGs removed.
# - Expected output: test-NN-out.pgn
test-NN:
echo "test-NN:"
$(PGN_EXTRACT) -N -otest-NN-out.pgn --quiet $(INPUT)$(SEP)test-N.pgn
$(CMP) test-NN-out.pgn $(OUTPUT)$(SEP)test-NN-out.pgn
# Comments after multiple nags.
$(PGN_EXTRACT) -otest-nagcomments-out.pgn --quiet $(INPUT)$(SEP)test-nagcomments.pgn
# Deleting NAGs with comments after multiple nags.
$(PGN_EXTRACT) -N -atest-nagcomments-out.pgn --quiet $(INPUT)$(SEP)test-nagcomments.pgn
$(CMP) test-nagcomments-out.pgn $(OUTPUT)$(SEP)test-nagcomments-out.pgn
$(CMP) test-nagcomments-out.pgn $(OUTPUT)$(SEP)test-nagcomments-out.pgn
#
# -o $(SEP) --output
# + Input file containing games in any accepted format.
# - Input file(s): test-o.txt
# - Resulting output should contain the input game formatted in PGN.
# - Expected output: test-o-out.pgn
test-output:
echo "test-output:"
$(PGN_EXTRACT) -otest-o-out.pgn --quiet $(INPUT)$(SEP)test-o.txt
$(CMP) test-o-out.pgn $(OUTPUT)$(SEP)test-o-out.pgn
$(PGN_EXTRACT) --output test-o-out.pgn --quiet $(INPUT)$(SEP)test-o.txt
$(CMP) test-o-out.pgn $(OUTPUT)$(SEP)test-o-out.pgn
# -P
# + Input file containing games with different sequences for the same
# opening.
# - Input file(s): test-P.pgn, Pvars.txt
# - Resulting output should be games whose opening move exactly match
# the sequence specified in Pvars.txt
# - Expected output: test-PP-out.pgn
test-PP:
echo "test-PP:"
$(PGN_EXTRACT) -P -v$(INPUT)$(SEP)Pvars.txt -otest-PP-out.pgn --quiet $(INPUT)$(SEP)test-P.pgn
$(CMP) test-PP-out.pgn $(OUTPUT)$(SEP)test-PP-out.pgn
# -r
# + Input file containing games in any accepted format.
# - Input file(s): test-r.text
# - Resulting output should contain tag summary lines for the games
# matched and a report of any errors.
# - Expected output: test-r-log.txt
test-r:
echo "test-r:"
$(PGN_EXTRACT) -r -ltest-r-log.txt $(INPUT)$(SEP)test-r.txt
# $(CMP) test-r-log.txt $(OUTPUT)$(SEP)test-r-log.txt
# -R
# + Input file containing games.
# - Input file(s): test-R.pgn, roster.txt
# - Resulting output should contain games with their tag roster in
# the order specified in roster.txt
# - Expected output: test-R-out.pgn
test-RR:
echo "test-RR:"
$(PGN_EXTRACT) -R$(INPUT)$(SEP)roster.txt --output test-RR-out.pgn --quiet $(INPUT)$(SEP)test-R.pgn
$(CMP) test-RR-out.pgn $(OUTPUT)$(SEP)test-RR-out.pgn
# -s
# + Input file containing games.
# - Input file(s): test-s.pgn
# - Resulting output should be silent, with games written to the output file.
# - Expected output: test-s-out.pgn
test-s:
echo "test-s:"
$(PGN_EXTRACT) -s -o test-s-out.pgn $(INPUT)$(SEP)test-s.pgn
$(CMP) test-s-out.pgn $(OUTPUT)$(SEP)test-s-out.pgn
# -S
# + Input file containing games whose players' names have slight
# sound variations from anglesized versions.
# - Input file(s): test-ucS.pgn
# - Resulting output should be games that match by ignoring slight
# soundex differences.
# - Expected output: test-SS-out.pgn
test-SS:
echo "test-SS:"
$(PGN_EXTRACT) -S -TpPetrosian -otest-SS-out.pgn --quiet $(INPUT)$(SEP)test-ucS.pgn
$(CMP) test-SS-out.pgn $(OUTPUT)$(SEP)test-SS-out.pgn
# -t
# + Input file containing games and a file of tag criteria.
# - Input file(s): test-t.pgn, taglist.txt
# - Resulting output should be only those games whose tags match
# all of the criteria.
# - Expected output: test-t-out.pgn
test-t:
echo "test-t:"
$(PGN_EXTRACT) -t$(INPUT)$(SEP)taglist.txt -otest-t-out.pgn --quiet $(INPUT)$(SEP)test-t.pgn
$(CMP) test-t-out.pgn $(OUTPUT)$(SEP)test-t-out.pgn
$(PGN_EXTRACT) -t$(INPUT)$(SEP)test-tFEN.txt -otest-tFEN-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-tFEN-out.pgn $(OUTPUT)$(SEP)test-tFEN-out.pgn
# -T
# + Input file containing games with tag information.
# - Input file(s): fischer.pgn, test-Ta.pgn (and eco.pgn for -Te test.)
# - Resulting output should contain only those games whose tag information
# matches that specified.
# - Expected output: test-Ta-out.pgn, test-Tb-out.pgn, test-Td-out.pgn,
# test-Tdd-out.pgn test-Te-out.pgn, test-Tp-out.pgn,
# test-Tw-out.pgn
test-TT:
echo "test-TT:"
$(PGN_EXTRACT) -Td1970 -otest-TTd-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-TTd-out.pgn $(OUTPUT)$(SEP)test-TTd-out.pgn
$(PGN_EXTRACT) -Td1960 -Td1962 -otest-TTdd-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-TTdd-out.pgn $(OUTPUT)$(SEP)test-TTdd-out.pgn
$(PGN_EXTRACT) -TbPetrosian -otest-TTb-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-TTb-out.pgn $(OUTPUT)$(SEP)test-TTb-out.pgn
$(PGN_EXTRACT) -e$(ECO_FILE) -TeB14 -otest-Te-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(PGN_EXTRACT) -TpPetrosian -otest-TTp-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-TTp-out.pgn $(OUTPUT)$(SEP)test-TTp-out.pgn
$(PGN_EXTRACT) -Tr0-1 -otest-TTr-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-TTr-out.pgn $(OUTPUT)$(SEP)test-TTr-out.pgn
$(PGN_EXTRACT) -TwFischer -otest-TTw-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-TTw-out.pgn $(OUTPUT)$(SEP)test-TTw-out.pgn
$(PGN_EXTRACT) -TaBarnes -otest-TTa-out.pgn --quiet $(INPUT)$(SEP)test-Ta.pgn
$(CMP) test-TTa-out.pgn $(OUTPUT)$(SEP)test-TTa-out.pgn
# -U $(SEP) --nounique
# + Input file containing games with duplicates and non-duplicates.
# - Input file(s): fischer.pgn, petrosian.pgn
# - Resulting output should be a file containing just the duplicate games.
# - Expected output: test-U-unique.pgn
test-nounique:
echo "test-nounique:"
$(PGN_EXTRACT) -U -otest-UU-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-UU-unique.pgn $(OUTPUT)$(SEP)test-UU-unique.pgn
$(PGN_EXTRACT) --nounique -otest-UU-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-UU-unique.pgn $(OUTPUT)$(SEP)test-UU-unique.pgn
# -v
# + Input file containing games.
# - Input file(s): najdorf.pgn, vvars.txt
# - Resulting output should be only those games whose opening moves
# textually match (in any order) the moves in vars.txt.
# - Expected output: test-v-out.pgn
test-v:
echo "test-v:"
$(PGN_EXTRACT) -v$(INPUT)$(SEP)vvars.txt -otest-v-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(CMP) test-v-out.pgn $(OUTPUT)$(SEP)test-v-out.pgn
# -V
# + Input file containing games with variations
# - Input file(s): test-V.pgn
# - Resulting output should have all variations removed.
# - Expected output: test-V-out.pgn
test-VV:
echo "test-VV:"
$(PGN_EXTRACT) -V -otest-VV-out.pgn --quiet $(INPUT)$(SEP)test-V.pgn
$(CMP) test-VV-out.pgn $(OUTPUT)$(SEP)test-VV-out.pgn
# -w $(SEP) --linelength
# + Input file containing games.
# - Input file(s): test-w.pgn
# - Resulting output Games formatted up to the specified line length.
# The default is 75.
# - Expected output: test-w60-out.pgn, test-w75-out.pgn, test-w1000-out.pgn
test-linelength:
echo "test-linelength:"
$(PGN_EXTRACT) -w60 -otest-w60-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn
$(CMP) test-w60-out.pgn $(OUTPUT)$(SEP)test-w60-out.pgn
$(PGN_EXTRACT) -w75 -otest-w75-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn
$(CMP) test-w75-out.pgn $(OUTPUT)$(SEP)test-w75-out.pgn
$(PGN_EXTRACT) -w1000 -otest-w1000-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn
$(CMP) test-w1000-out.pgn $(OUTPUT)$(SEP)test-w1000-out.pgn
$(PGN_EXTRACT) --linelength 60 -otest-w60-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn
$(CMP) test-w60-out.pgn $(OUTPUT)$(SEP)test-w60-out.pgn
$(PGN_EXTRACT) --linelength 75 -otest-w75-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn
$(CMP) test-w75-out.pgn $(OUTPUT)$(SEP)test-w75-out.pgn
$(PGN_EXTRACT) --linelength 1000 -otest-w1000-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn
$(CMP) test-w1000-out.pgn $(OUTPUT)$(SEP)test-w1000-out.pgn
# -W
# + Input file containing games.
# - Input file(s): test-ucW.pgn
# - Resulting output should be games formatted in the specified notation:
# halg (hyphenated long algebraic), lalg (non-hyphenated long algebraic),
# elalg (enhanced long algebraic), xlalg (enhanced with capture info),
# uci (UCI-compatible output),
# and alternative piece letters.
# - Expected output: test-WWhalg-out.pgn, test-WWlalg-out.pgn,
# test-WWelalg-out.pgn, test-WWdeutsch-out.pgn,
# test-WWuci-out.pgn
test-WW:
echo "test-WW:"
$(PGN_EXTRACT) -Whalg -otest-WWhalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWhalg-out.pgn $(OUTPUT)$(SEP)test-WWhalg-out.pgn
$(PGN_EXTRACT) -Wlalg -otest-WWlalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWlalg-out.pgn $(OUTPUT)$(SEP)test-WWlalg-out.pgn
$(PGN_EXTRACT) -Welalg -otest-WWelalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWelalg-out.pgn $(OUTPUT)$(SEP)test-WWelalg-out.pgn
$(PGN_EXTRACT) -Wxlalg -otest-WWxlalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWxlalg-out.pgn $(OUTPUT)$(SEP)test-WWxlalg-out.pgn
$(PGN_EXTRACT) -WsanBSLTDK -otest-WWdeutsch-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWdeutsch-out.pgn $(OUTPUT)$(SEP)test-WWdeutsch-out.pgn
$(PGN_EXTRACT) -Wuci -otest-WWuci-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWuci-out.pgn $(OUTPUT)$(SEP)test-WWuci-out.pgn
$(PGN_EXTRACT) -Wepd -otest-WWepd-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn
$(CMP) test-WWepd-out.pgn $(OUTPUT)$(SEP)test-WWepd-out.pgn
# -x
# + Input file containing games.
# - Input file(s): najdorf.pgn, xvars.txt
# - Resulting output should be only those games which match
# the result of reaching the opening sequence in vars.txt.
# - Expected output: test-x-out.pgn
test-x:
echo "test-x:"
$(PGN_EXTRACT) -x$(INPUT)$(SEP)xvars.txt -otest-x-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(CMP) test-x-out.pgn $(OUTPUT)$(SEP)test-x-out.pgn
$(PGN_EXTRACT) -x$(INPUT)$(SEP)xvars.txt -otest-x-out.pgn -ntest-xn-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(CMP) test-xn-out.pgn $(OUTPUT)$(SEP)test-xn-out.pgn
# -y
# + Input file containing games.
# - Input file(s): fischer.pgn, zmatch.txt
# - Resulting output should be games whose material balance matches that
# specified in ymatch.txt
# - Expected output: test-y-out.pgn
test-y:
echo "test-y:"
$(PGN_EXTRACT) -y$(INPUT)$(SEP)ymatch.txt --markmatches MATCH -otest-y-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-y-out.pgn $(OUTPUT)$(SEP)test-y-out.pgn
$(PGN_EXTRACT) --materialy "q*r*p*b2n2< q=r=p=b2<n2" --markmatches MATCH -otest-y-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-y-out.pgn $(OUTPUT)$(SEP)test-y-out.pgn
# -z
# + Input file containing games.
# - Input file(s): fischer.pgn, zmatch.txt
# - Resulting output should be games whose material balance matches that
# specified in zmatch.txt
# - Expected output: test-z-out.pgn
test-z:
echo "test-z:"
$(PGN_EXTRACT) -z$(INPUT)$(SEP)zmatch.txt -otest-z-out.pgn --markmatches MATCH --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-z-out.pgn $(OUTPUT)$(SEP)test-z-out.pgn
$(PGN_EXTRACT) --materialz "q*r*p*b2n2< q=r=p=b2<n2" -otest-z-out.pgn --markmatches MATCH --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-z-out.pgn $(OUTPUT)$(SEP)test-z-out.pgn
# -Z
# + Input file containing games with duplicates and non-duplicates.
# - Input file(s): fischer.pgn, petrosian.pgn
# - Resulting output should be files separating the unique and
# duplicated games in the input files.
# - Expected output: test-ZZ-unique.pgn, test-ZZ-dupes.pgn
test-ZZ:
echo "test-ZZ:"
$(PGN_EXTRACT) -C -Z -dtest-ZZ-dupes.pgn -otest-ZZ-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn
$(CMP) test-ZZ-dupes.pgn $(OUTPUT)$(SEP)test-ZZ-dupes.pgn
$(CMP) test-ZZ-unique.pgn $(OUTPUT)$(SEP)test-ZZ-unique.pgn
# -#
# + Input file containing games.
# - Input file(s): test-hash.pgn
# - Resulting output The input file split in to separate sub-files,
# each containing 10 games, except the last which may contain fewer.
# - Expected output: 1.pgn, 2.pgn
test-hash:
echo "test-hash:"
$(PGN_EXTRACT) -#20 --quiet $(INPUT)$(SEP)test-hash.pgn
$(CMP) 1.pgn $(OUTPUT)$(SEP)1.pgn
$(CMP) 2.pgn $(OUTPUT)$(SEP)2.pgn
$(PGN_EXTRACT) -#20,10 --quiet $(INPUT)$(SEP)test-hash.pgn
$(CMP) 10.pgn $(OUTPUT)$(SEP)10.pgn
$(CMP) 11.pgn $(OUTPUT)$(SEP)11.pgn
# --evaluation
# + Input file containing games.
# - Input file(s): test-evaluation.pgn
# - Resulting output should include an evaluation value in a comment
# after every move.
# - Expected output: test-evaluation-out.pgn
test-evaluation:
echo "test-evaluation:"
$(PGN_EXTRACT) --evaluation -otest-evaluation-out.pgn --quiet $(INPUT)$(SEP)test-evaluation.pgn
$(CMP) test-evaluation-out.pgn $(OUTPUT)$(SEP)test-evaluation-out.pgn
# --fencomments
# + Input file containing games.
# - Input file(s): test-fencomments.pgn
# - Resulting output should have a comment after every move containing a
# FEN description of the position after that move.
# - Expected output: test-fencomments-out.pgn
test-fencomments:
echo "test-fencomments:"
$(PGN_EXTRACT) --fencomments -otest-fencomments-out.pgn --quiet $(INPUT)$(SEP)test-fencomments.pgn
$(CMP) test-fencomments-out.pgn $(OUTPUT)$(SEP)test-fencomments-out.pgn
# --markmatches
# + Input file containing games.
# - Input file(s): najdorf.pgn, xvars.txt
# - Resulting output should be only those games which match
# the result of reaching the opening sequence in vars.txt.
# The point of each match is marked with the comment { MATCH }
# - Expected output: test-markmatches-out.pgn
test-markmatches:
echo "test-markmatches:"
$(PGN_EXTRACT) --markmatches MATCH -x$(INPUT)$(SEP)xvars.txt -otest-markmatches-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(CMP) test-markmatches-out.pgn $(OUTPUT)$(SEP)test-markmatches-out.pgn
# --nestedcomments
# + Input file containing games.
# - Input file(s): nested-comment.pgn
# - Resulting output should have retained the nested comment.
# - Expected output: test-nestedcomments-out.pgn
test-nestedcomments:
echo "test-nestedcomments:"
$(PGN_EXTRACT) --nestedcomments -otest-nestedcomments-out.pgn --quiet $(INPUT)$(SEP)nested-comment.pgn
$(CMP) test-nestedcomments-out.pgn $(OUTPUT)$(SEP)test-nestedcomments-out.pgn
# --nochecks
# + Input file containing games with moves involving moves that give check
# and$(SEP)or mate.
# - Input file(s): test-nochecks.pgn
# - Resulting output should contain games with no check indicators after moves.
# - Expected output: test-nochecks-out.pgn
test-nochecks:
echo "test-nochecks:"
$(PGN_EXTRACT) --nochecks -otest-nochecks-out.pgn --quiet $(INPUT)$(SEP)test-nochecks.pgn
$(CMP) test-nochecks-out.pgn $(OUTPUT)$(SEP)test-nochecks-out.pgn
# --nomovenumbers
# + Input file containing games with move numbers.
# - Input file(s): test-nomovenumbers.pgn
# - Resulting output should contain games with no move numbers.
# - Expected output: test-nomovenumbers-out.pgn
test-nomovenumbers:
echo "test-nomovenumbers:"
$(PGN_EXTRACT) -otest-nomovenumbers-out.pgn --nomovenumbers --quiet $(INPUT)$(SEP)test-nomovenumbers.pgn
$(CMP) test-nomovenumbers-out.pgn $(OUTPUT)$(SEP)test-nomovenumbers-out.pgn
# --noresults
# + Input file containing games with results.
# - Input file(s): test-noresults.pgn
# - Resulting output should contain games with no results.
# - Expected output: test-noresults-out.pgn
test-noresults:
echo "test-noresults:"
$(PGN_EXTRACT) -otest-noresults-out.pgn --noresults --quiet $(INPUT)$(SEP)test-noresults.pgn
$(CMP) test-noresults-out.pgn $(OUTPUT)$(SEP)test-noresults-out.pgn
# --notags
# + Input file containing games with tag information.
# - Input file(s): test-notags.pgn
# - Resulting output should contain games with no tag information.
# - Expected output: test-notags-out.pgn
test-notags:
echo "test-notags:"
$(PGN_EXTRACT) -otest-notags-out.pgn --notags --quiet $(INPUT)$(SEP)test-notags.pgn
$(CMP) test-notags-out.pgn $(OUTPUT)$(SEP)test-notags-out.pgn
# --plylimit
# + Input file containing games.
# - Input file(s): test-plylimit.pgn
# - Resulting output should contain games whose number of moves (plies) are
# limited at the specified ply limit.
# - Expected output: test-plylimit-out.pgn
test-plylimit:
echo "test-plylimit:"
$(PGN_EXTRACT) --plylimit 10 -otest-plylimit-out.pgn --quiet $(INPUT)$(SEP)test-plylimit.pgn
$(CMP) test-plylimit-out.pgn $(OUTPUT)$(SEP)test-plylimit-out.pgn
# --dropply
# + Input file containing games.
# - Input file(s): najdorf.pgn
# - Resulting output should contain games whose number of moves (plies) are
# have been reduced by the given number from the beginning or end.
# - Expected output: test-dropply-out.pgn
test-dropply:
echo "test-dropply:"
$(PGN_EXTRACT) --dropply 10 -otest-dropply-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(PGN_EXTRACT) --dropply 11 -atest-dropply-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(PGN_EXTRACT) --dropply -1 -atest-dropply-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(PGN_EXTRACT) --dropply -2 -atest-dropply-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn
$(CMP) test-dropply-out.pgn $(OUTPUT)$(SEP)test-dropply-out.pgn
# --selectonly
# + Input file containing games.
# - Input file(s): test-selectonly.pgn
# - Resulting output should contain only two matched games.
# - Expected output: test-selectonly-out.pgn
test-selectonly:
echo "test-selectonly:"
$(PGN_EXTRACT) -TpPetrosian --selectonly 2,3 -otest-selectonly-out.pgn --quiet $(INPUT)$(SEP)test-selectonly.pgn
$(CMP) test-selectonly-out.pgn $(OUTPUT)$(SEP)test-selectonly-out.pgn
# --skipmatching
# + Input file containing games.
# - Input file(s): test-skipmatching.pgn
# - Resulting output should contain a single matched game.
# - Expected output: test-selectonly-out.pgn
test-skipmatching:
echo "test-skipmatching:"
$(PGN_EXTRACT) -TpKeres --skipmatching 1,2 -otest-skipmatching-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn
$(CMP) test-skipmatching-out.pgn $(OUTPUT)$(SEP)test-skipmatching-out.pgn
# --splitvariants
# + Input file containing games.
# - Input file(s): test-splitvariants.pgn
# - Resulting output should contain a separate game
# for every variation in the input file.
# - Expected output: test-splitvariants-out.pgn
test-splitvariants:
echo "test-splitvariants:"
$(PGN_EXTRACT) --splitvariants -otest-splitvariants-out.pgn --quiet $(INPUT)$(SEP)test-splitvariants.pgn
$(CMP) test-splitvariants-out.pgn $(OUTPUT)$(SEP)test-splitvariants-out.pgn
# --stalemate
# + Input file containing games.
# - Input file(s): test-stalemate.pgn
# - Resulting output should contain only those games that end in stalemate.
# - Expected output: test-stalemate-out.pgn
test-stalemate:
echo "test-stalemate:"
$(PGN_EXTRACT) --stalemate -otest-stalemate-out.pgn --quiet $(INPUT)$(SEP)test-stalemate.pgn
$(CMP) test-stalemate-out.pgn $(OUTPUT)$(SEP)test-stalemate-out.pgn
# --fifty
# + Input file containing games.
# - Input file(s): test-fifty.pgn
# - Resulting output should contain only those games to which the fifty-move rule
# applies, with the comment { FIFTY } at the approriate point.
# - Expected output: test-fifty-out.pgn
test-fifty:
echo "test-fifty:"
$(PGN_EXTRACT) --fifty --markmatches FIFTY -otest-fifty-out.pgn --quiet $(INPUT)$(SEP)test-fifty.pgn
$(CMP) test-fifty-out.pgn $(OUTPUT)$(SEP)test-fifty-out.pgn
# --seventyfive
# + Input file containing games.
# - Input file(s): test-seventyfive.pgn
# - Resulting output should contain only those games to which the seventy-five-move rule
# applies, with the comment { SEVENTYFIVE } at the approriate point.
# - Expected output: test-seventyfive-out.pgn
test-seventyfive:
echo "test-seventyfive:"
$(PGN_EXTRACT) --seventyfive --markmatches SEVENTYFIVE -otest-seventyfive-out.pgn --quiet $(INPUT)$(SEP)test-seventyfive.pgn
$(CMP) test-seventyfive-out.pgn $(OUTPUT)$(SEP)test-seventyfive-out.pgn
# --repetition
# + Input file containing games.
# - Input file(s): test-repetition.pgn
# - Resulting output should contain only those games which contain a 3-fold repetition,
# with the comment { REPEAT } at the approriate point.
# - Expected output: test-repetition-out.pgn
test-repetition:
echo "test-repetition:"
$(PGN_EXTRACT) --repetition --markmatches REPEAT -otest-repetition-out.pgn --quiet $(INPUT)$(SEP)test-repetition.pgn
$(CMP) test-repetition-out.pgn $(OUTPUT)$(SEP)test-repetition-out.pgn
# --plycount and --totalplycount
# + Input file containing games.
# - Input file(s): test-plycount.pgn
# - Resulting output should contain games with PlyCount and TotalPlyCount tags.
# - Expected output: test-plycount-out.pgn
test-plycount:
echo "test-plycount:"
$(PGN_EXTRACT) --plycount --totalplycount -otest-plycount-out.pgn --quiet $(INPUT)$(SEP)test-plycount.pgn
$(CMP) test-plycount-out.pgn $(OUTPUT)$(SEP)test-plycount-out.pgn
# --addhashcode
# + Input file containing games.
# - Input file(s): test-addhashcode.pgn
# - Resulting output should contain games with a HashCode tag.
# - Expected output: test-addhashcode-out.pgn
test-addhashcode:
echo "test-addhashcode:"
$(PGN_EXTRACT) --addhashcode -otest-addhashcode-out.pgn --quiet $(INPUT)$(SEP)test-addhashcode.pgn
$(CMP) test-addhashcode-out.pgn $(OUTPUT)$(SEP)test-addhashcode-out.pgn
# Test on a file with a string too long to be output within the
# defined line length.
# + Input file containing a game with a very long comment.
# + Input file(s): test-long-line.pgn
# + Resulting output should contain the game properly formatted and
# the log file should contain an error message reporting the problem.
# + Expected output: test-long-line-out.pgn, test-long-line-log.txt
test-long-line:
echo "test long line:"
$(PGN_EXTRACT) -otest-long-line-out.pgn -ltest-long-line-log.txt $(INPUT)$(SEP)test-long-line.pgn
$(CMP) test-long-line-out.pgn $(OUTPUT)$(SEP)test-long-line-out.pgn
# $(CMP) test-long-line-log.txt $(OUTPUT)$(SEP)test-long-line-log.txt
# Promotion characters.
# + Input file with games involving a promotion
# - Input file(s): test-promotion-in.pgn
# - Game output should have all games with promotions.
# - Expected output: test-promotion-out.pgn
test-promotion:
echo "test-promotion:"
$(PGN_EXTRACT) -otest-promotion-out.pgn --quiet $(INPUT)$(SEP)test-promotion-in.pgn
$(CMP) test-promotion-out.pgn $(OUTPUT)$(SEP)test-promotion-out.pgn
$(PGN_EXTRACT) --underpromotion -otest-underpromotion-out.pgn --quiet $(INPUT)$(SEP)test-promotion-in.pgn
$(CMP) test-underpromotion-out.pgn $(OUTPUT)$(SEP)test-underpromotion-out.pgn
# Inconsistent Result tags
# + Input file with games where the Result tag conflicts with checkmate or stalemate.
# - Input file(s): test-fixresulttags-in.pgn
# - Game output should have consistent Result tags
# - Expected output: test-fixresulttags-out.pgn
test-fixresulttags:
echo "test-fixresulttags:"
$(PGN_EXTRACT) --fixresulttags -otest-fixresulttags-out.pgn -lfix-results-log.txt --quiet $(INPUT)$(SEP)test-fixresulttags-in.pgn
$(CMP) test-fixresulttags-out.pgn $(OUTPUT)$(SEP)test-fixresulttags-out.pgn
# $(CMP) fix-results-log.txt $(OUTPUT)$(SEP)fix-results-log.txt
# --fuzzydepth
# + Input file containing games with fuzzy duplicates and non-duplicates.
# - Input file(s): $(INPUT)$(SEP)test-fuzzydepth.pgn
# - Resulting output should be files separating the unique and
# duplicated games in the input files.
# - Expected output: test-fuzzydepth0-unique.pgn, test-fuzzydepth0-dupes.pgn
test-fuzzydepth:
echo "test-duplicates:"
$(PGN_EXTRACT) -C --fuzzydepth 0 -dtest-fuzzydepth0-dupes.pgn -otest-fuzzydepth0-unique.pgn --quiet $(INPUT)$(SEP)test-fuzzydepth.pgn
$(CMP) test-fuzzydepth0-dupes.pgn $(OUTPUT)$(SEP)test-fuzzydepth0-dupes.pgn
$(CMP) test-fuzzydepth0-unique.pgn $(OUTPUT)$(SEP)test-fuzzydepth0-unique.pgn
$(PGN_EXTRACT) -C --fuzzydepth 3 -dtest-fuzzydepth3-dupes.pgn -otest-fuzzydepth3-unique.pgn --quiet $(INPUT)$(SEP)test-fuzzydepth.pgn
$(CMP) test-fuzzydepth3-dupes.pgn $(OUTPUT)$(SEP)test-fuzzydepth3-dupes.pgn
$(CMP) test-fuzzydepth3-unique.pgn $(OUTPUT)$(SEP)test-fuzzydepth3-unique.pgn
$(PGN_EXTRACT) -C --fuzzydepth 4 -dtest-fuzzydepth4-dupes.pgn -otest-fuzzydepth4-unique.pgn --quiet $(INPUT)$(SEP)test-fuzzydepth.pgn
$(CMP) test-fuzzydepth4-dupes.pgn $(OUTPUT)$(SEP)test-fuzzydepth4-dupes.pgn
$(CMP) test-fuzzydepth4-unique.pgn $(OUTPUT)$(SEP)test-fuzzydepth4-unique.pgn
$(PGN_EXTRACT) -C --fuzzydepth 5 -dtest-fuzzydepth5-dupes.pgn -otest-fuzzydepth5-unique.pgn --quiet $(INPUT)$(SEP)test-fuzzydepth.pgn
$(CMP) test-fuzzydepth5-dupes.pgn $(OUTPUT)$(SEP)test-fuzzydepth5-dupes.pgn
$(CMP) test-fuzzydepth5-unique.pgn $(OUTPUT)$(SEP)test-fuzzydepth5-unique.pgn
# Selection or exclusion of games with SetUp tags.
# + Input file with games involving SetUp tags.
# - Input file(s): test-setup-in.pgn
# - Game output should either have only games with SetUp tags
# or only those without.
# - Expected output: test-nosetup-out.pgn test-onlysetup-out.pgn
test-setup:
echo "test-setup:"
$(PGN_EXTRACT) --nosetuptags -otest-nosetup-out.pgn --quiet $(INPUT)$(SEP)test-setup-in.pgn
$(CMP) test-nosetup-out.pgn $(OUTPUT)$(SEP)test-nosetup-out.pgn
$(PGN_EXTRACT) --onlysetuptags -otest-onlysetup-out.pgn --quiet $(INPUT)$(SEP)test-setup-in.pgn
$(CMP) test-onlysetup-out.pgn $(OUTPUT)$(SEP)test-onlysetup-out.pgn
# --stopafter
# + Input file containing games.
# - Input file(s): test-stopafter.pgn
# - Resulting output should contain a single matched game.
# - Expected output: test-stopafter-out.pgn
test-stopafter:
echo "test-stopafter:"
$(PGN_EXTRACT) -TpPetrosian --stopafter 1 -otest-stopafter-out.pgn --quiet $(INPUT)$(SEP)test-stopafter.pgn
$(CMP) test-stopafter-out.pgn $(OUTPUT)$(SEP)test-stopafter-out.pgn
# --nobadresults
# + Input file containing games with inconsistent or incomplete results.
# - Input file(s): test-nobadresults.pgn
# - Resulting output should contain only those games which are not
# strictly inconsistent.
# - Expected output: test-nobadresults-out.pgn
test-nobadresults:
echo "test-nobadresults:"
$(PGN_EXTRACT) --nobadresults -otest-nobadresults-out.pgn -ltest-nobadresults-log.txt --quiet $(INPUT)$(SEP)test-nobadresults.pgn
$(CMP) test-nobadresults-out.pgn $(OUTPUT)$(SEP)test-nobadresults-out.pgn
# $(CMP) test-nobadresults-log.txt $(OUTPUT)$(SEP)test-nobadresults-log.txt
# --allownullmoves
# + Input file containing games with inconsistent or incomplete results.
# - Input file(s): test-allownullmoves.pgn
# - Resulting output should contain only those games which are not
# strictly inconsistent.
# - Expected output: test-allownullmoves-out.pgn
test-allownullmoves:
echo "test-allownullmoves:"
$(PGN_EXTRACT) --allownullmoves -otest-allownullmoves-out.pgn -ltest-allownullmoves-log.txt --quiet $(INPUT)$(SEP)test-allownullmoves.pgn
$(CMP) test-allownullmoves-out.pgn $(OUTPUT)$(SEP)test-allownullmoves-out.pgn
# $(CMP) test-allownullmoves-log.txt $(OUTPUT)$(SEP)test-allownullmoves-log.txt
# --matchplylimit
# + Input file containing games.
# - Input file(s): test-matchplylimit.pgn
# - Resulting output should contain games whose number of moves (plies) are
# limited at the specified ply limit.
# - Expected output: test-matchplylimit-out.pgn
test-matchplylimit:
echo "test-matchplylimit:"
-$(RM) test-matchplylimit-out.pgn
$(PGN_EXTRACT) -Hdb55d4fcaadc775e --matchplylimit 8 --markmatches match -atest-matchplylimit-out.pgn --quiet $(INPUT)$(SEP)test-matchplylimit.pgn
$(PGN_EXTRACT) -Hdb55d4fcaadc775e --matchplylimit 9 --markmatches match -atest-matchplylimit-out.pgn --quiet $(INPUT)$(SEP)test-matchplylimit.pgn
$(PGN_EXTRACT) -Hdb55d4fcaadc775e --matchplylimit 10 --markmatches match -atest-matchplylimit-out.pgn --quiet $(INPUT)$(SEP)test-matchplylimit.pgn
$(PGN_EXTRACT) -Hdb55d4fcaadc775e --matchplylimit 150 --markmatches match -atest-matchplylimit-out.pgn --quiet $(INPUT)$(SEP)test-matchplylimit.pgn
$(CMP) test-matchplylimit-out.pgn $(OUTPUT)$(SEP)test-matchplylimit-out.pgn
# -A/-t with FENPattern and FENPatternI
# Test both FENPattern and FENPatternI and add a MatchLabel tag
# if the pattern has an associated label.
test-FENPattern:
echo "test-FENPattern:"
$(PGN_EXTRACT) -otest-FENPattern-out.pgn -ltest-FENPattern-log.txt --quiet \
-A$(INPUT)$(SEP)test-FENPattern.txt --addlabeltag --markmatches HERE \
$(INPUT)$(SEP)petrosian.pgn
$(CMP) test-FENPattern-out.pgn $(OUTPUT)$(SEP)test-FENPattern-out.pgn
$(PGN_EXTRACT) -otest-FENPattern-cli-out.pgn -ltest-FENPattern-log.txt --quiet \
--fenpattern "*/*/*/*/???pN???/???P????/*/*" \
--fenpatterni "*/*/*/*/???Np???/????P???/*/*" \
--markmatches HERE \
$(INPUT)$(SEP)petrosian.pgn
$(CMP) test-FENPattern-cli-out.pgn $(OUTPUT)$(SEP)test-FENPattern-cli-out.pgn
# $(CMP) test-FENPattern-log.txt $(OUTPUT)$(SEP)test-FENPattern-log.txt
# --startply
# + Input file containing games.
# - Input file(s): test-startply.pgn
# - Resulting output should contain games matching the given FEN pattern,
# only starting the match at the specified ply.
# - Expected output: test-startply-out.pgn
test-startply:
echo "test-startply:"
-$(RM) test-startply-out.pgn
$(PGN_EXTRACT) --startply 8 -Tf"*/*/4p3/3pP3/2pP4/2P5/*/*" --markmatches match -atest-startply-out.pgn --quiet $(INPUT)$(SEP)test-startply.pgn
$(PGN_EXTRACT) --startply 9 -Tf"*/*/4p3/3pP3/2pP4/2P5/*/*" --markmatches match -atest-startply-out.pgn --quiet $(INPUT)$(SEP)test-startply.pgn
$(PGN_EXTRACT) --startply 10 -Tf"*/*/4p3/3pP3/2pP4/2P5/*/*" --markmatches match -atest-startply-out.pgn --quiet $(INPUT)$(SEP)test-startply.pgn
$(PGN_EXTRACT) --startply 11 -Tf"*/*/4p3/3pP3/2pP4/2P5/*/*" --markmatches match -atest-startply-out.pgn --quiet $(INPUT)$(SEP)test-startply.pgn
$(PGN_EXTRACT) --startply 100 -Tf"*/*/4p3/3pP3/2pP4/2P5/*/*" --markmatches match -atest-startply-out.pgn --quiet $(INPUT)$(SEP)test-startply.pgn
$(PGN_EXTRACT) --startply 200 -Tf"*/*/4p3/3pP3/2pP4/2P5/*/*" --markmatches match -atest-startply-out.pgn --quiet $(INPUT)$(SEP)test-startply.pgn
$(CMP) test-startply-out.pgn $(OUTPUT)$(SEP)test-startply-out.pgn
test-linenumbers:
echo "test-linenumbers:"
-$(RM) test-linenumbers-out.pgn
$(PGN_EXTRACT) --quiet --linenumbers marker infiles/petrosian.pgn -o test-linenumbers-out.pgn
$(CMP) test-linenumbers-out.pgn $(OUTPUT)$(SEP)test-linenumbers-out.pgn

View File

@@ -0,0 +1 @@
c4 Nf6 Nc3 e6 d4 Bb4

View File

@@ -0,0 +1,6 @@
b2b3 e7e5 c1b2 d7d6 d2d4 e5d4 d1d4 b8c6 d4d2 g8f6 b1c3 c8e6 e2e4 d6d5 e4d5
e6d5 d2e3+ f8e7 g1f3 e8g8 f1e2 f8e8 e1c1 e7b4 e3d3 b4c3 b2c3 d8e7 h1e1 f6e4
c3b2 a8d8 d3e3 b7b6 e2b5 e7e6 f3d4 c6d4 d1d4 c7c5 d4e4 d5e4 b5e8 d8e8 f2f3
e4d5 e3e6 e8e6 e1e6 d5e6 c1d2 g8f8 b2e5 b6b5 e5b8 a7a6 b8a7 c5c4 d2c3 f8e7
c3d4 e7d6 a7c5+ d6d7 c5a7 d7d6 a7c5+ d6d7 d4c3 g7g6 c5d4 f7f5 1/2-1/2

View File

@@ -0,0 +1,15 @@
% Strip variations.
:--novars
% Silent mode
:-s
% Duplicates file.
:-dtest-AA-dupes.pgn
% Unique file.
:--output test-AA-unique.pgn
% Tag criteria
:-t
White "Fischer"
Black "Petrosian"
% The game files.
:infiles/fischer.pgn
:infiles/petrosian.pgn

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1 @@
infiles/petrosian.pgn

View File

@@ -0,0 +1,2 @@
infiles/test-f1.pgn
infiles/test-f2.pgn

View File

@@ -0,0 +1,581 @@
[Event "Milwaukee Northwestern"]
[Site "?"]
[Date "1957"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Kampars, N."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 e6 6. d4 Nd7 7. Bd3 dxe4
8. Nxe4 Ngf6 9. O-O Nxe4 10. Qxe4 Nf6 11. Qe3 Nd5 12. Qf3 Qf6 13. Qxf6 Nxf6
14. Rd1 O-O-O 15. Be3 Nd5 16. Bg5 Be7 17. Bxe7 Nxe7 18. Be4 Nd5 19. g3 Nf6
20. Bf3 Kc7 21. Kf1 Rhe8 22. Be2 e5 23. dxe5 Rxe5 24. Bc4 Rxd1+ 25. Rxd1
Re7 26. Bb3 Ne4 27. Rd4 Nd6 28. c3 f6 29. Bc2 h6 30. Bd3 Nf7 31. f4 Rd7 32.
Rxd7+ Kxd7 33. Kf2 Nd6 34. Kf3 f5 35. Ke3 c5 36. Be2 Ke6 37. Bd3 1/2-1/2
[Event "US Open"]
[Site "?"]
[Date "1957"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Addison, William G."]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. Bc4 Bd6 7. Qe2+
Qe7 8. Qxe7+ Kxe7 9. d4 Bf5 10. Bb3 Re8 11. Be3 Kf8 12. O-O-O Nd7 13. c4
Rad8 14. Bc2 Bxc2 15. Kxc2 f5 16. Rhe1 f4 17. Bd2 Nf6 18. Ne5 g5 19. f3 Nh5
20. Ng4 Kg7 21. Bc3 Kg6 22. Rxe8 Rxe8 23. c5 Bb8 24. d5 cxd5 25. Rxd5 f5
26. Ne5+ Bxe5 27. Rxe5 Nf6 28. Rxe8 Nxe8 29. Be5 Kh5 30. Kd3 g4 31. b4 a6
32. a4 gxf3 33. gxf3 Kh4 34. b5 axb5 35. a5 Kh3 36. c6 1-0
[Event "West Orange Open"]
[Site "?"]
[Date "1957"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Goldsmith, Julius"]
[Result "1-0"]
1. e4 c6 2. Nc3 d6 3. d4 Nd7 4. Nf3 e5 5. Bc4 Be7 6. dxe5 Nxe5 7. Nxe5 dxe5
8. Qh5 g6 9. Qxe5 Nf6 10. Bg5 Bd7 11. O-O-O O-O 12. Rxd7 Qxd7 13. Bxf6 Bxf6
14. Qxf6 Rae8 15. f3 Qc7 16. h4 Qe5 17. Qxe5 Rxe5 18. Rd1 Re7 19. Rd6 Kg7
20. a3 f5 21. Kd2 fxe4 22. Nxe4 Rf4 23. h5 gxh5 24. Rd8 h4 25. Rg8+ Kh6 26.
Ke3 Rf5 27. Rg4 Rh5 28. Kf2 Rg7 29. Rxg7 Kxg7 30. Bf1 Rd5 31. Bd3 h6 32.
Ke3 Rh5 33. Nd6 h3 34. gxh3 Rxh3 35. Nxb7 Rh5 36. b4 Re5+ 37. Kf4 Re7 38.
Nd8 c5 39. bxc5 Kf6 40. c6 Rc7 41. Be4 Ke7 42. Nb7 Kf6 43. Nd6 Re7 44. c7
1-0
[Event "Bad Portoroz Interzonal"]
[Site "?"]
[Date "1958"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Cardoso, Rudolfo T."]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Bg4 5. h3 Bxf3 6. Qxf3 Nd7 7. Ng5
Ngf6 8. Qb3 e6 9. Qxb7 Nd5 10. Ne4 Nb4 11. Kd1 f5 12. c3 Rb8 13. Qxa7 fxe4
14. cxb4 Bxb4 15. Qd4 O-O 16. Bc4 Nc5 17. Qxd8 Rbxd8 18. Rf1 Rd4 19. b3
Bxd2 20. Ke2 Bxc1 21. Raxc1 Rfd8 22. Rfd1 Kf8 23. Rxd4 Rxd4 24. Rd1 Rxd1
25. Kxd1 Ke7 26. Kd2 Kd6 27. Kc3 Nd7 28. Kd4 Nf6 29. a4 c5+ 30. Ke3 g5 31.
Be2 Kc6 32. Bc4 e5 33. a5 h6 34. Kd2 h5 35. Ke3 h4 36. Be2 Kb7 37. Bc4 Kc6
38. Ke2 Kb7 39. Kd2 Kc6 40. Ke3 Kb7 41. Kd2 Kc7 42. g4 Kc6 43. Kc3 Ne8 44.
b4 Nd6 45. Bf1 cxb4+ 46. Kxb4 Nc8 47. Bg2 Kd5 48. a6 Na7 49. Ka5 Kc5 50.
Bxe4 Nb5 51. Bg2 Na7 52. Ka4 Nb5 53. Kb3 Kb6 54. Kc4 Kxa6 55. Kd5 Kb6 56.
Kxe5 Kc7 57. Kf6 Nc3 58. Kxg5 Nd1 59. f4 Kd6 60. Kxh4 Ke6 61. Kg5 Kf7 62.
f5 1-0
[Event "USA Championship"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Weinstein, Raymond"]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Be7 8.
Bg2 dxe4 9. dxe4 e5 10. O-O Nbd7 11. Nd1 O-O 12. Ne3 g6 13. Rd1 Qc7 14. Ng4
h5 15. Nxf6+ Nxf6 16. Bg5 Nh7 17. Bh6 Rfd8 18. Bf1 Bg5 19. Bxg5 Nxg5 20.
Qe3 Qe7 21. h4 Ne6 22. Bc4 b5 23. Bxe6 Qxe6 24. Qc5 Qc4 25. Qxc4 bxc4 26.
b3 Rd4 27. Rxd4 exd4 28. Kf1 Re8 29. f3 Re5 30. Rd1 c5 31. c3 dxc3 32. Rc1
f5 33. exf5 Rxf5 34. Rxc3 cxb3 35. Rxb3 c4 36. Ra3 Rc5 37. Ke2 c3 38. Kd1
c2+ 39. Kc1 a5 40. Rb3 Kg7 41. Rb7+ Kf6 42. Rb6+ Kg7 43. g4 1/2-1/2
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Benko, Pal"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 a5 11. a3 Bxd2+ 12. Nxd2 Qc5 13. Qd1 h5 14. h4
Nbd7 15. Bg2 Ng4 16. O-O g5 17. b4 Qe7 18. Nf3 gxh4 19. Nxh4 Nde5 20. Qd2
Rg8 21. Qf4 f6 22. bxa5 Rxa5 23. Rfb1 b5 24. Nf3 Ra4 25. Bh3 Nxf3+ 26. Qxf3
Kd7 27. Kg2 Qg7 28. Rb4 Rga8 29. Rxa4 Rxa4 30. Bxg4 hxg4 31. Qf4 Ra8 32.
Rh1 Rg8 33. a4 bxa4 34. Rb1 e5 35. Rb7+ Kd6 36. Rxg7 exf4 37. Rxg8 f3+ 38.
Kh1 Kc5 39. Rb8 1-0
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 Nbd7 11. Bg2 a5 12. a3 Bxd2+ 13. Nxd2 Qc5 14. Qd1
h5 15. Nf3 Qc3+ 16. Ke2 Qc5 17. Qd2 Ne5 18. b4 Nxf3 19. Bxf3 Qe5 20. Qf4
Nd7 21. Qxe5 Nxe5 22. bxa5 Kd7 23. Rhb1 Kc7 24. Rb4 Rxa5 25. Bg2 g5 26. f4
gxf4 27. gxf4 Ng6 28. Kf3 Rg8 29. Bf1 e5 30. fxe5 Nxe5+ 31. Ke2 c5 32. Rb3
b6 33. Rab1 Rg6 34. h4 Ra6 35. Bh3 Rg3 36. Bf1 Rg4 37. Bh3 Rxh4 38. Rh1 Ra8
39. Rbb1 Rg8 40. Rbf1 Rg3 41. Bf5 Rg2+ 42. Kd1 Rhh2 43. Rxh2 Rxh2 44. Rg1
c4 45. dxc4 Nxc4 46. Rg7 Kd6 47. Rxf7 Ne3+ 48. Kc1 Rxc2+ 49. Kb1 Rh2 50.
Rd7+ Ke5 51. Re7+ Kf4 52. Rd7 Nd1 53. Kc1 Nc3 54. Bh7 h4 55. Rf7+ Ke3 0-1
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 a5 11. a3 Be7 12. Bg2 a4 13. b4 Nbd7 14. O-O c5
15. Ra2 O-O 16. bxc5 Bxc5 17. Qe2 e5 18. f4 Rfc8 19. h4 Rc6 20. Bh3 Qc7 21.
fxe5 Nxe5 22. Bf4 Bd6 23. h5 Ra5 24. h6 Ng6 25. Qf3 Rh5 26. Bg4 Nxf4 27.
Bxh5 N4xh5 28. g4 Bh2+ 29. Kg2 Nxg4 30. Nd2 Ne3+ 0-1
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Olafsson, Fridrik"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 Nf6 4. e5 Ne4 5. Ne2 Qb6 6. d4 c5 7. dxc5 Qxc5 8.
Ned4 Nc6 9. Bb5 a6 10. Bxc6+ bxc6 11. O-O Qb6 12. e6 fxe6 13. Bf4 g6 14.
Be5 Nf6 15. Ng5 Bh6 16. Ndxe6 Bxg5 17. Nxg5 O-O 18. Qd2 Bf5 19. Rae1 Rad8
20. Bc3 Rd7 21. Ne6 Bxe6 22. Rxe6 d4 23. Bb4 Nd5 24. Ba3 Rf7 25. g3 Nc7 26.
Re5 Nd5 27. Qd3 Nf6 28. Qc4 Ng4 29. Re6 Qb5 30. Qxb5 axb5 31. Rxc6 Ne5 32.
Rc8+ Kg7 33. Bb4 Nf3+ 34. Kg2 e5 35. Rd1 g5 36. Bf8+ Rxf8 37. Rxf8 Kxf8 38.
Kxf3 Kf7 39. c3 Ke6 40. cxd4 exd4 41. Ke4 Rf7 42. f3 1-0
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Smyslov, Vasily V."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bh5 5. exd5 cxd5 6. Bb5+ Nc6 7. g4 Bg6
8. Ne5 Rc8 9. h4 f6 10. Nxg6 hxg6 11. d4 e6 12. Qd3 Kf7 13. h5 gxh5 14.
gxh5 Nge7 15. Be3 Nf5 16. Bxc6 Rxc6 17. Ne2 Qa5+ 18. c3 Qa6 19. Qc2 Bd6 20.
Bf4 Bxf4 21. Nxf4 Rh6 22. Qe2 Qxe2+ 23. Kxe2 Rh8 24. Kd3 b5 25. Rhe1 b4 26.
cxb4 Rc4 27. Nxe6 Rxh5 28. b3 Rh3+ 29. Kd2 Rcc3 30. Nf4 Rhf3 31. Re2 g5 32.
Nxd5 Rcd3+ 33. Kc1 Rxd4 34. Ne3 Nxe3 35. fxe3 Rxb4 36. Kd2 g4 37. Rc1 Rb7
38. Rg1 Rd7+ 39. Kc2 f5 40. e4 Kf6 41. exf5 g3 42. Re8 Rg7 43. Rf8+ Ke7 44.
Ra8 Kd6 45. Rf8 Rf2+ 46. Kd3 g2 47. f6 Rg3+ 48. Kc4 Ke6 49. Re1+ Kf5 50. f7
Rg7 51. Rg1 Kf6 52. a4 Rxf7 1/2-1/2
[Event "?"]
[Site "Yugoslavia, Bled"]
[Date "1959.??.??"]
[Round "02"]
[White "Fischer, R."]
[Black "Petrosian, T."]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Bxd2+ 10. Nxd2 e5 11. Bg2 c5 12. O-O Nc6 13. Qe2 g5 14. Nf3
h6 15. h4 Rg8 16. a3 Qe7 17. hxg5 hxg5 18. Qd2 Nd7 19. c3 O-O-O 20. cxd4
exd4 21. b4 Kb8 22. Rfc1 Nce5 23. Nxe5 Qxe5 24. Rc4 Rc8 25. Rac1 g4 26. Qb2
Rgd8 27. a4 Qe7 28. Rb1 Ne5 29. Rxc5 Rxc5 30. bxc5 Nxd3 31. Qd2 Nxc5 32.
Qf4+ Qc7 33. Qxg4 Nxa4 34. e5 Nc5 35. Qf3 d3 36. Qe3 d2 37. Bf3 Na4 38. Qe4
Nc5 39. Qe2 a6 40. Kg2 Ka7 41. Qe3 Rd3 42. Qf4 Qd7 43. Qc4 b6 44. Rd1 a5
45. Qf4 Rd4 46. Qh6 b5 47. Qe3 Kb6 48. Qh6+ Ne6 49. Qe3 Ka6 50. Be2 a4 51.
Qc3 Kb6 52. Qe3 Nc5 53. Bf3 b4 54. Qh6+ Ne6 55. Qh8 Qd8 56. Qh7 Qd7 57. Qh8
b3 58. Qb8+ Ka5 59. Qa8+ Kb5 60. Qb8+ Kc4 61. Qg8 Kc3 62. Bh5 Nd8 63. Bf3
a3 64. Qf8 Kb2 65. Qh8 Ne6 66. Qa8 a2 67. Qa5 Qa4 68. Rxd2+ Ka3 0-1
[Event "?"]
[Site "Yugoslavia, Zagreb"]
[Date "1959.??.??"]
[Round "16"]
[White "Fischer, R."]
[Black "Petrosian, T."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Bxd2+ 10. Nxd2 e5 11. Bg2 c5 12. O-O Nc6 13. Qe2 Qe7 14. f4
O-O-O 15. a3 Ne8 16. b4 cxb4 17. Nc4 f6 18. fxe5 fxe5 19. axb4 Nc7 20. Na5
Nb5 21. Nxc6 bxc6 22. Rf2 g6 23. h4 Kb7 24. h5 Qxb4 25. Rf7+ Kb6 26. Qf2 a5
27. c4 Nc3 28. Rf1 a4 29. Qf6 Qc5 30. Rxh7 Rdf8 31. Qxg6 Rxh7 32. Qxh7
Rxf1+ 33. Bxf1 a3 34. h6 a2 35. Qg8 a1=Q 36. h7 Qd6 37. h8=Q Qa7 38. g4 Kc5
39. Qf8 Qae7 40. Qa8 Kb4 41. Qh2 Kb3 42. Qa1 Qa3 43. Qxa3+ Kxa3 44. Qh6 Qf7
45. Kg2 Kb3 46. Qd2 Qh7 47. Kg3 Qxe4 48. Qf2 Qh1 1/2-1/2
[Event "Zurich"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Larsen, Bent"]
[Result "1/2-1/2"]
1. e4 c6 2. Nf3 d5 3. Nc3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. a3 Bc5 8.
Be2 O-O 9. O-O Nbd7 10. Qg3 Bd4 11. Bh6 Ne8 12. Bg5 Ndf6 13. Bf3 Qd6 14.
Bf4 Qc5 15. Rab1 dxe4 16. dxe4 e5 17. Bg5 Bxc3 18. bxc3 b5 19. c4 a6 20.
Bd2 Qe7 21. Bb4 Nd6 22. Rfd1 Rfd8 23. cxb5 cxb5 24. Rd3 Qe6 25. Rbd1 Nb7
26. Bc3 Rxd3 27. cxd3 Re8 28. Kh2 h6 29. d4 Nd6 30. Re1 Nc4 31. dxe5 Nxe5
32. Bd1 Ng6 33. e5 Nd5 34. Bb3 Qc6 35. Bb2 Ndf4 36. Rd1 a5 37. Rd6 Qe4 38.
Rd7 Ne6 39. Bd5 Qe2 40. Bc3 b4 41. axb4 axb4 42. Bxb4 Qxe5 43. Ba5 Qxg3+
44. Kxg3 Re7 45. Rd6 Nef4 46. Bf3 Ne6 47. Bb6 Ne5 48. Bd5 Rd7 49. Rxd7 Nxd7
50. Be3 Nf6 51. Bc6 g5 52. Kf3 Kg7 53. Ba4 Nd5 54. Bc1 h5 55. Bb2+ Kh6 56.
Bb3 Ndf4 57. Bc2 Ng6 58. Kg3 Nef4 59. Be4 Nh4 60. Bf6 Nhg6 61. Kf3 Nh4+ 62.
Kg3 Nhg6 63. Kh2 h4 64. Kg1 Nh5 65. Bc3 Ngf4 66. Kf1 Ng7 67. Bf6 Nfh5 68.
Be5 f6 69. Bd6 f5 70. Bf3 Nf4 71. Ke1 Kg6 72. Kd2 Nge6 73. Be5 Nc5 74. Ke3
Nce6 75. Bc6 Kf7 76. Kf3 Ke7 77. Bb7 Ng6 78. Bc3 Ngf4 79. Ba6 Nd5 80. Be5
Nf6 81. Bd3 g4+ 82. Ke2 Nd7 83. Bh2 gxh3 84. gxh3 Kf6 85. Ke3 Ne5 86. Be2
Ng6 87. Bf1 f4+ 88. Kf3 Ne5+ 89. Ke4 Ng5+ 90. Kxf4 Nef3 91. Bg3 hxg3 92.
fxg3 1/2-1/2
[Event "Buenos Aires"]
[Site "?"]
[Date "1960"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Foguelman, Alberto"]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nh3 Nf6 7. Nf4 e5
8. dxe5 Qxd1+ 9. Kxd1 Ng4 10. Nxg6 hxg6 11. Ne4 Nxe5 12. Be2 f6 13. c3 Nbd7
14. Be3 O-O-O 15. Kc2 Nb6 16. h4 Nec4 17. Bf4 Nd5 18. Bg3 Nd6 19. Nxd6+
Bxd6 20. Bxd6 Rxd6 21. g3 Kc7 22. c4 Nb4+ 23. Kc3 c5 24. a3 Re8 25. Bf1 Nc6
26. Bd3 Ne5 27. Be4 Ng4 28. Bxg6 Re2 29. Rae1 Rxf2 30. Re7+ Kb6 31. Be4 Re2
32. Rxb7+ Ka6 33. Re7 Kb6 34. b4 Nf2 35. Rb7+ Ka6 36. b5+ Ka5 37. Rxa7+ Kb6
38. Ra6+ Kc7 39. b6+ Rxb6 40. Rxb6 Nxe4+ 41. Kd3 Kxb6 42. Rg1 Rd2+ 43. Kxe4
Rd4+ 44. Kf5 Rxc4 45. Re1 Rc3 46. g4 Rf3+ 47. Kg6 Rxa3 48. Kxg7 Rg3 49. Re4
f5 50. Re6+ Kb5 51. g5 Rg4 52. g6 Rxh4 53. Kf7 c4 54. g7 Rh7 55. Rg6 c3 56.
Kf6 Rxg7 57. Rxg7 Kc4 58. Kxf5 c2 1/2-1/2
[Event "Buenos Aires"]
[Site "?"]
[Date "1960"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Ivkov, Boris"]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 6. Nf3 Be7 7. c5 O-O 8.
b4 b6 9. Bd3 bxc5 10. bxc5 Nc6 11. O-O Bd7 12. h3 Ne8 13. Bf4 Bf6 14. Bb5
Nc7 15. Be2 Nxd4 16. Nxd4 e5 17. c6 Be8 18. Bg3 exd4 19. Bxc7 Qxc7 20. Nxd5
Qd6 21. Nxf6+ Qxf6 22. c7 Rc8 23. Rc1 Bc6 24. Rc4 Rxc7 25. Bd3 Rd7 26. Qc2
Bd5 27. Ra4 g6 28. Qc5 Rfd8 29. Bb5 Rd6 30. Rd1 Be6 31. Bd3 Rd5 32. Qxa7
Bxh3 33. Be4 R5d7 34. Qa6 Qxa6 35. Rxa6 Be6 36. a4 d3 37. Rd2 Rd4 38. f3
Bd5 39. Bxd5 R8xd5 40. Kf2 Rc4 41. a5 Ra4 42. Rc6 Ra3 43. Rc1 h5 44. Rcd1
Kg7 45. a6 g5 46. a7 Rxa7 47. Rxd3 Ra2+ 48. Kg1 Rxd3 49. Rxd3 Kg6 50. Kh2
Ra4 51. Rd5 g4 52. fxg4 hxg4 53. g3 Kf6 54. Rd7 Ke5 55. Kg2 f5 56. Rd2 Rc4
57. Re2+ Kd4 58. Rf2 Rc5 59. Rf4+ Ke3 60. Kg1 1/2-1/2
[Event "Leipzig Olympiad Final"]
[Site "?"]
[Date "1960"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Euwe, Max"]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Nc6 6. Nf3 Bg4 7. cxd5 Nxd5
8. Qb3 Bxf3 9. gxf3 e6 10. Qxb7 Nxd4 11. Bb5+ Nxb5 12. Qc6+ Ke7 13. Qxb5
Nxc3 14. bxc3 Qd7 15. Rb1 Rd8 16. Be3 Qxb5 17. Rxb5 Rd7 18. Ke2 f6 19. Rd1
Rxd1 20. Kxd1 Kd7 21. Rb8 Kc6 22. Bxa7 g5 23. a4 Bg7 24. Rb6+ Kd5 25. Rb7
Bf8 26. Rb8 Bg7 27. Rb5+ Kc6 28. Rb6+ Kd5 29. a5 f5 30. Bb8 Rc8 31. a6 Rxc3
32. Rb5+ Kc4 33. Rb7 Bd4 34. Rc7+ Kd3 35. Rxc3+ Kxc3 36. Be5 1-0
[Event "Bled"]
[Site "?"]
[Date "1961"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d4 dxe4 7. Qe3 Nbd7
8. Nxe4 Nxe4 9. Qxe4 Nf6 10. Qd3 Qd5 11. c4 Qd6 12. Be2 e5 13. d5 e4 14.
Qc2 Be7 15. dxc6 Qxc6 16. O-O O-O 17. Be3 Bc5 18. Qc3 b6 19. Rfd1 Rfd8 20.
b4 Bxe3 21. fxe3 Qc7 22. Rd4 a5 23. a3 axb4 24. axb4 h5 25. Rad1 Rxd4 26.
Qxd4 Qg3 27. Qxb6 Ra2 28. Bf1 h4 29. Qc5 Qf2+ 30. Kh1 g6 31. Qe5 Kg7 32. c5
Qxe3 33. c6 Rc2 34. b5 Rc1 35. Rxc1 Qxc1 36. Kg1 e3 37. c7 e2 38. Qxe2 Qxc7
39. Qf2 g5 40. b6 Qe5 41. b7 Nd7 42. Qd2 Nb8 43. Be2 Kf6 44. Bf3 Ke6 45.
Bg4+ f5 46. Bd1 Kf6 47. Qd8+ Kg6 48. Qg8+ Kh6 49. Qf8+ Kg6 50. Qg8+ Kh6 51.
Qf8+ Kg6 52. Qb4 Nc6 53. Qd2 Nd8 54. Bf3 Nxb7 55. Bxb7 Qa1+ 56. Kh2 Qe5+
1/2-1/2
[Event "Bled"]
[Site "?"]
[Date "1961"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Nf3 Ngf6 6. Nxf6+ Nxf6 7. Bc4
Bf5 8. Qe2 e6 9. Bg5 Bg4 10. O-O-O Be7 11. h3 Bxf3 12. Qxf3 Nd5 13. Bxe7
Qxe7 14. Kb1 Rd8 15. Qe4 b5 16. Bd3 a5 17. c3 Qd6 18. g3 b4 19. c4 Nf6 20.
Qe5 c5 21. Qg5 h6 22. Qxc5 Qxc5 23. dxc5 Ke7 24. c6 Rd6 25. Rhe1 Rxc6 26.
Re5 Ra8 27. Be4 Rd6 28. Bxa8 Rxd1+ 29. Kc2 Rf1 30. Rxa5 Rxf2+ 31. Kb3 Rh2
32. c5 Kd8 33. Rb5 Rxh3 34. Rb8+ Kc7 35. Rb7+ Kc6 36. Kc4 1-0
[Event "Stockholm Interzonal"]
[Site "?"]
[Date "1962"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Barcza, Gedeon"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. d4 Bd6 7. Bc4
O-O 8. O-O Re8 9. Bb3 Nd7 10. Nh4 Nf8 11. Qd3 Bc7 12. Be3 Qe7 13. Nf5 Qe4
14. Qxe4 Rxe4 15. Ng3 Re8 16. d5 cxd5 17. Bxd5 Bb6 18. Bxb6 axb6 19. a3 Ra5
20. Rad1 Rc5 21. c3 Rc7 22. Bf3 Rd7 23. Rxd7 Nxd7 24. Nf5 Nc5 25. Nd6 Rd8
26. Nxc8 Rxc8 27. Rd1 Kf8 28. Rd4 Rc7 29. h3 f5 30. Rb4 Nd7 31. Kf1 Ke7 32.
Ke2 Kd8 33. Rb5 g6 34. Ke3 Kc8 35. Kd4 Kb8 36. Kd5 Rc6 37. Kd4 Re6 38. a4
Kc7 39. a5 Rd6+ 40. Bd5 Kc8 41. axb6 f6 42. Ke3 Nxb6 43. Bg8 Kc7 44. Rc5+
Kb8 45. Bxh7 Nd5+ 46. Kf3 Ne7 47. h4 b6 48. Rb5 Kb7 49. h5 Ka6 50. c4 gxh5
51. Bxf5 Rd4 52. b3 Nc6 53. Ke3 Rd8 54. Be4 Na5 55. Bc2 h4 56. Rh5 Re8+ 57.
Kd2 Rg8 58. Rxh4 b5 59. Rf4 bxc4 60. bxc4 Rxg2 61. Rxf6+ Ka7 62. Kc3 Rg4
63. f4 Nb7 64. Kb4 1-0
[Event "Varna Olympiad Final"]
[Site "?"]
[Date "1962"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Donner, Jan H."]
[Result "0-1"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 h6 7. Nf3 Nd7 8.
Bd3 Bxd3 9. Qxd3 e6 10. Bf4 Qa5+ 11. Bd2 Qc7 12. c4 Ngf6 13. Bc3 a5 14. O-O
Bd6 15. Ne4 Nxe4 16. Qxe4 O-O 17. d5 Rfe8 18. dxc6 bxc6 19. Rad1 Bf8 20.
Nd4 Ra6 21. Nf5 Nc5 22. Qe3 Na4 23. Be5 Qa7 24. Nxh6+ gxh6 25. Rd4 f5 26.
Rfd1 Nc5 27. Rd8 Qf7 28. Rxe8 Qxe8 29. Bd4 Ne4 30. f3 e5 31. fxe4 exd4 32.
Qg3+ Bg7 33. exf5 Qe3+ 34. Qxe3 dxe3 35. Rd8+ Kf7 36. Rd7+ Kf6 37. g4 Bf8
38. Kg2 Bc5 39. Rh7 Ke5 40. Kf3 Kd4 41. Rxh6 Rb6 42. b3 a4 43. Re6 axb3 44.
axb3 Kd3 0-1
[Event "USA Championship"]
[Site "?"]
[Date "1963"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Steinmeyer, Robert H."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nf3 Nf6 7. h4 h6 8.
Bd3 Bxd3 9. Qxd3 e6 10. Bd2 Nbd7 11. O-O-O Qc7 12. c4 O-O-O 13. Bc3 Qf4+
14. Kb1 Nc5 15. Qc2 Nce4 16. Ne5 Nxf2 17. Rdf1 1-0
[Event "Skopje"]
[Site "?"]
[Date "1967"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Panov, Vasil"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. Bc4 Bd6 7. O-O
O-O 8. d4 Be6 9. Bxe6 fxe6 10. Re1 Re8 11. c4 Na6 12. Bd2 Qd7 13. Bc3 Bb4
14. Qb3 Bxc3 15. bxc3 Nc7 16. a4 b6 17. h3 Rab8 18. Re4 a6 19. Qc2 b5 20.
axb5 axb5 21. cxb5 cxb5 22. Nd2 Ra8 23. Rae1 Qd5 24. Rh4 Qf5 25. Ne4 e5 26.
Re3 h6 27. Rf3 Qh7 28. Nxf6+ gxf6 29. Rg3+ Kh8 30. Rg6 1-0
[Event "Nathania"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Cagan, Shimon"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. a3 Nbd7 8.
g4 Bd6 9. g5 Ng8 10. h4 Ne7 11. h5 Qb6 12. Bh3 O-O-O 13. a4 a5 14. O-O Rhf8
15. Kh1 f5 16. Qg2 g6 17. h6 Kb8 18. f4 Rfe8 19. e5 Bc5 20. Qf3 Nc8 21. Bg2
Kc7 22. Ne2 Nb8 23. c3 Kd7 24. Bd2 Na6 25. Rfb1 Bf8 26. b4 axb4 27. cxb4
Bxb4 28. a5 Qc5 29. d4 Qf8 30. Bxb4 Nxb4 31. Qc3 Na6 32. Rxb7+ Nc7 33. Nc1
Re7 34. a6 1-0
[Event "Nathania"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Czerniak, Moshe"]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Bd3 Nc6 5. c3 Nf6 6. Bf4 g6 7. Nf3 Bg7 8.
Nbd2 Nh5 9. Be3 O-O 10. O-O f5 11. Nb3 Qd6 12. Re1 f4 13. Bd2 Bg4 14. Be2
Rae8 15. Nc1 Bxf3 16. Bxf3 e5 17. Qb3 exd4 18. Nd3 Rd8 19. c4 dxc4 20.
Qxc4+ Kh8 21. Re6 Qb8 22. Rae1 Rc8 23. Bxc6 Rxc6 24. Rxc6 bxc6 25. Qxc6 Qc8
26. Qxc8 Rxc8 27. Kf1 Bh6 28. Rc1 Rxc1+ 29. Bxc1 g5 30. b4 Kg8 31. b5 Kf7
32. Ba3 Bf8 33. Ne5+ Ke6 34. Bxf8 Kxe5 35. Bc5 Nf6 36. Bxa7 Ne4 37. f3 Nd2+
38. Ke2 Nc4 39. b6 Na5 40. b7 Nxb7 41. Kd3 h5 42. Bxd4+ Kd5 43. h3 Nd8 44.
a4 Ne6 45. Bb6 g4 46. hxg4 hxg4 47. fxg4 1-0
[Event "Nathania"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Yanofsky, Daniel A."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 g6 6. Qb3 Bg7 7. cxd5 O-O
8. Be2 Na6 9. Bg5 Qb6 10. Qxb6 axb6 11. a3 Rd8 12. Bxf6 Bxf6 13. Rd1 Bf5
14. Bc4 Rac8 15. Bb3 b5 16. Nf3 b4 17. axb4 Nxb4 18. Ke2 Bc2 19. Bxc2 Nxc2
20. Kd3 Nb4+ 21. Ke4 Rd6 22. Ne5 Bg7 23. g4 f5+ 24. gxf5 gxf5+ 25. Kf4 Rf8
26. Rhg1 Nxd5+ 27. Nxd5 Rxd5 28. Nf3 Kh8 29. Rge1 Bf6 30. Ne5 e6 31. h4 Rc8
32. Nf7+ Kg7 33. Ng5 Bxg5+ 34. Kxg5 Rc6 35. Re5 Rcd6 36. Rxd5 Rxd5 37. f4
Rb5 38. Rd2 Rb3 39. d5 h6+ 40. Kh5 exd5 41. Rxd5 Rxb2 42. Rd7+ Kf6 43. Rd6+
Kf7 44. Rxh6 Rg2 45. Rb6 Rg4 46. Rxb7+ Kf6 1/2-1/2
[Event "Vinkovci"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Hort, Vlastimil"]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Nf3 Nf6 5. c3 Bf5 6. Bb5+ Nbd7 7. Nh4 Bg6
8. Bf4 e6 9. Nd2 Nh5 10. Nxg6 hxg6 11. Be3 Bd6 12. g3 a6 13. Bd3 Rc8 14.
O-O Nb6 15. a4 Rc7 16. Qb3 Nc8 17. c4 dxc4 18. Nxc4 Nf6 19. Rac1 O-O 20.
Bd2 Nd5 21. Be4 Be7 22. Na5 Ncb6 23. Bxd5 Nxd5 24. Nxb7 Qb8 25. Rxc7 Qxc7
26. Rc1 Qb8 27. Rc4 Rd8 28. Bc3 Rd7 29. Na5 Qxb3 30. Rc8+ Kh7 31. Nxb3 Nb6
32. Rc6 Nxa4 33. Rxa6 Nxc3 34. bxc3 Rc7 35. Nd2 Rxc3 36. Ra7 Rd3 37. Nf1
Bf6 38. Rxf7 Rxd4 39. Kg2 g5 40. h3 Kg6 41. Rc7 Ra4 42. Nd2 Rd4 43. Nb3 Rd6
44. Nc5 Kf5 45. Kf3 Rb6 46. Rd7 Rc6 47. Ne4 Ra6 48. Rd3 Be7 49. Rb3 Ra3 50.
Rxa3 Bxa3 51. g4+ Kg6 52. Ke3 Bc1+ 53. Kd4 Bf4 54. Kc5 Kf7 55. Kb6 Ke8 56.
Kc6 Ke7 1/2-1/2
[Event "Palma de Mallorca"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Hubner, Robert"]
[Result "1/2-1/2"]
1. e4 c6 2. d3 d5 3. Nd2 g6 4. g3 Bg7 5. Bg2 e5 6. Ngf3 Ne7 7. O-O O-O 8.
Re1 d4 9. a4 c5 10. Nc4 Nbc6 11. c3 Be6 12. cxd4 Bxc4 13. dxc4 exd4 14. e5
Qd7 15. h4 d3 16. Bd2 Rad8 17. Bc3 Nb4 18. Nd4 Rfe8 19. e6 fxe6 20. Nxe6
Bxc3 21. bxc3 Nc2 22. Nxd8 Rxd8 23. Qd2 Nxa1 24. Rxa1 Kg7 25. Re1 Ng8 26.
Bd5 Qxa4 27. Qxd3 Re8 28. Rxe8 Qxe8 29. Bxb7 Nf6 30. Qd6 Qd7 31. Qa6 Qf7
32. Qxa7 Ne4 33. f3 Nd6 34. Qxc5 Nxb7 35. Qd4+ Kg8 36. Kf2 Qe7 37. Qd5+ Kf8
38. h5 gxh5 39. Qxh5 Nc5 40. Qd5 Kg7 41. Qd4+ Kf7 42. Qd5+ Kg7 43. Qd4+ Kf7
44. Qd5+ 1/2-1/2
[Event "Siegen Olympiad Final"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Hort, Vlastimil"]
[Result "1/2-1/2"]
1. e4 c6 2. d3 d5 3. Nd2 g6 4. g3 Bg7 5. Bg2 e5 6. Ngf3 Ne7 7. O-O O-O 8.
Re1 Nd7 9. b3 d4 10. Bb2 b5 11. c3 c5 12. Rc1 Bb7 13. cxd4 cxd4 14. Bh3 Nc6
15. a3 Re8 16. Qe2 Rc8 17. Rc2 Ne7 18. Rec1 Rxc2 19. Rxc2 Nc6 20. Qd1 Nb6
21. Qc1 Qf6 22. Bg2 Rc8 23. h4 Bf8 24. Bh3 Rc7 25. Nh2 Bc8 26. Bf1 Bd7 27.
h5 Rc8 28. Be2 Nd8 29. Rxc8 Bxc8 30. Ndf3 Nc6 31. Nh4 b4 32. axb4 Nxb4 33.
N4f3 a5 34. Qc7 Qd6 35. Qa7 Ba6 36. Ba3 Nc8 37. Qa8 Qb6 38. Bxb4 Bxb4 39.
Qd5 Qc5 40. Qxe5 Qxe5 41. Nxe5 Nd6 42. hxg6 hxg6 43. Kf1 Bb5 44. Nhf3 Bc3
45. Ne1 Nb7 46. Bd1 Nc5 47. f3 Kg7 48. Bc2 Kf6 49. Ng4+ Ke7 50. Nf2 Bd7 51.
Nd1 Bb4 52. Nb2 Be6 53. Nc4 Bxc4 54. dxc4 Bxe1 55. Kxe1 g5 56. Ke2 Kd6 57.
f4 gxf4 58. gxf4 f6 59. Kf3 Ke6 60. Ke2 Kd6 1/2-1/2
[Event "Siegen Olympiad Prelim"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Ibrahimoglu, Ismet"]
[Result "1-0"]
1. e4 c6 2. d3 d5 3. Nd2 g6 4. Ngf3 Bg7 5. g3 Nf6 6. Bg2 O-O 7. O-O Bg4 8.
h3 Bxf3 9. Qxf3 Nbd7 10. Qe2 dxe4 11. dxe4 Qc7 12. a4 Rad8 13. Nb3 b6 14.
Be3 c5 15. a5 e5 16. Nd2 Ne8 17. axb6 axb6 18. Nb1 Qb7 19. Nc3 Nc7 20. Nb5
Qc6 21. Nxc7 Qxc7 22. Qb5 Ra8 23. c3 Rxa1 24. Rxa1 Rb8 25. Ra6 Bf8 26. Bf1
Kg7 27. Qa4 Rb7 28. Bb5 Nb8 29. Ra8 Bd6 30. Qd1 Nc6 31. Qd2 h5 32. Bh6+ Kh7
33. Bg5 Rb8 34. Rxb8 Nxb8 35. Bf6 Nc6 36. Qd5 Na7 37. Be8 Kg8 38. Bxf7+
Qxf7 39. Qxd6 1-0
[Event "USSR-World"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Bd3 Nc6 5. c3 Nf6 6. Bf4 Bg4 7. Qb3 Na5
8. Qa4+ Bd7 9. Qc2 e6 10. Nf3 Qb6 11. a4 Rc8 12. Nbd2 Nc6 13. Qb1 Nh5 14.
Be3 h6 15. Ne5 Nf6 16. h3 Bd6 17. O-O Kf8 18. f4 Be8 19. Bf2 Qc7 20. Bh4
Ng8 21. f5 Nxe5 22. dxe5 Bxe5 23. fxe6 Bf6 24. exf7 Bxf7 25. Nf3 Bxh4 26.
Nxh4 Nf6 27. Ng6+ Bxg6 28. Bxg6 Ke7 29. Qf5 Kd8 30. Rae1 Qc5+ 31. Kh1 Rf8
32. Qe5 Rc7 33. b4 Qc6 34. c4 dxc4 35. Bf5 Rff7 36. Rd1+ Rfd7 37. Bxd7 Rxd7
38. Qb8+ Ke7 39. Rde1+ 1-0
[Event "USSR-World"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 g6 4. e5 Bg7 5. f4 h5 6. Nf3 Bg4 7. h3 Bxf3 8.
Qxf3 e6 9. g3 Qb6 10. Qf2 Ne7 11. Bd3 Nd7 12. Ne2 O-O-O 13. c3 f6 14. b3
Nf5 15. Rg1 c5 16. Bxf5 gxf5 17. Be3 Qa6 18. Kf1 cxd4 19. cxd4 Nb8 20. Kg2
Nc6 21. Nc1 Rd7 22. Qd2 Qa5 23. Qxa5 Nxa5 24. Nd3 Nc6 25. Rac1 Rc7 26. Rc3
b6 27. Rgc1 Kb7 28. Nb4 Rhc8 29. Rxc6 Rxc6 30. Rxc6 Rxc6 31. Nxc6 Kxc6 32.
Kf3 1/2-1/2
[Event "Zabreb"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Marovic, Drazen"]
[Result "1-0"]
1. e4 c6 2. d3 d5 3. Nd2 Nd7 4. Ngf3 Qc7 5. exd5 cxd5 6. d4 g6 7. Bd3 Bg7
8. O-O e6 9. Re1 Ne7 10. Nf1 Nc6 11. c3 O-O 12. Bg5 e5 13. Ne3 Nb6 14. dxe5
Nxe5 15. Bf4 f6 16. a4 Qf7 17. a5 Nbc4 18. Bxc4 dxc4 19. Bxe5 fxe5 20. Qe2
h6 21. Nxc4 Bg4 22. Ncxe5 Bxe5 23. Nxe5 Bxe2 24. Nxf7 Rxf7 25. Rxe2 Rd8 26.
Rae1 Rd5 27. b4 Rc7 28. Re3 Kf7 29. h4 Rd2 30. Rf3+ Kg7 31. Re6 Rf7 32.
Rxf7+ Kxf7 33. Re5 Rd1+ 34. Kh2 b6 35. axb6 axb6 36. f3 Rd3 37. Rb5 Rxc3
38. Rxb6 h5 39. Rb7+ Kf6 40. b5 Rb3 41. b6 Rb4 42. Kg3 Rb2 43. Rb8 Kg7 44.
f4 Rb3+ 45. Kf2 Kf6 46. Ke2 Kg7 47. Kd2 Rg3 48. Rc8 1-0
[Event "?"]
[Site "Stockholm"]
[Date "1962.??.??"]
[Round "4"]
[White "Fischer, Robert J."]
[Black "Portisch, Lajos"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Neg5 Nd5 7. d4 h6
8. Ne4 N7b6 9. Bb3 Bf5 10. Ng3 Bh7 11. O-O e6 12. Ne5 Nd7 13. c4 N5f6 14.
Bf4 Nxe5 15. Bxe5 Bd6 16. Qe2 O-O 17. Rad1 Qe7 18. Bxd6 Qxd6 19. f4 c5 20.
Qe5 Qxe5 21. dxe5 Ne4 22. Rd7 Nxg3 23. hxg3 Be4 24. Ba4 Rad8 25. Rfd1 Rxd7
26. Rxd7 g5 27. Bd1 Bc6 28. Rd6 Rc8 29. Kf2 Kf8 30. Bf3 Bxf3 31. gxf3 gxf4
32. gxf4 Ke7 33. f5 exf5 34. Rxh6 Rd8 35. Ke2 Rg8 36. Kf2 Rd8 37. Ke3 Rd1
38. b3 Re1+ 39. Kf4 Re2 40. Kxf5 Rxa2 41. f4 Re2 42. Rh3 Re1 43. Rd3 Rb1
44. Re3 Rb2 45. e6 a6 46. exf7+ Kxf7 47. Ke5 Rd2 48. Rc3 b6 49. f5 Rd1 50.
Rh3 b5 51. Rh7+ Kg8 52. Rb7 bxc4 53. bxc4 Rd4 54. Ke6 Re4+ 55. Kd5 Rf4 56.
Kxc5 Rxf5+ 57. Kd6 Rf6+ 58. Ke5 Rf7 59. Rb6 Rc7 60. Kd5 Kf7 61. Rxa6 Ke7
62. Re6+ Kd8 63. Rd6+ Ke7 64. c5 Rc8 65. c6 Rc7 66. Rh6 Kd8 67. Rh8+ Ke7
68. Ra8 1-0
[Event "?"]
[Site "Yugoslavia ct"]
[Date "1959.??.??"]
[Round "2"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 a5 11. a3 Be7 12. Bg2 a4 13. b4 Nbd7 14. O-O c5
15. Ra2 O-O 16. bxc5 Bxc5 17. Qe2 e5 18. f4 Rfc8 19. h4 Rc6 20. Bh3 Qc7 21.
fxe5 Nxe5 22. Bf4 Bd6 23. h5 Ra5 24. h6 Ng6 25. Qf3 Rh5 26. Bg4 Nxf4 27.
Bxh5 N4xh5 28. Kg2 Ng4 29. Nd2 Ne3+ 0-1

View File

@@ -0,0 +1,9 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4 Qh4# 0-1

View File

@@ -0,0 +1 @@
f3 e5 g4 Qh4 0-1

View File

@@ -0,0 +1,124 @@
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.15"]
[Round "7"]
[White "Arnason Jon L"]
[Black "Kristensen Bjarke"]
[Result "0-1"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. a4 Nc6 7. Bc4 Bd7 8.
O-O Rc8 9. Kh1 g6 10. f4 Bg7 11. Nf3 O-O 12. Ba2 b5 13. axb5 axb5 14. Qe1
Nb4 15. Bb3 Nxc2 16. Bxc2 b4 17. e5 dxe5 18. fxe5 Ng4 19. Bd2 bxc3 20. Bxc3
Bb5 21. Rg1 Bc6 22. Bd1 Qc7 23. Ra5 Rcd8 24. Qg3 Ne3 25. Ba4 Bb7 26. Qf2
Rd3 27. Rb1 Ba8 28. Qe2 Ng4 29. Rf1 Re3 30. Qd2 Qc4 31. Qd1 Rd3 32. Qa1
Rxf3 33. Rxf3 Bxf3 34. gxf3 Qf4 35. Qg1 Qxf3+ 36. Qg2 Nf2+ 37. Kg1 Nh3+ 38.
Kh1 Qe3 39. Bd2 Nf2+ 40. Kg1 Qxd2 41. Qxf2 Qc1+ 42. Qf1 Qe3+ 43. Qf2 Qg5+
44. Qg3 Qc1+ 45. Kg2 Rd8 46. Qf3 Qg5+ 47. Qg3 Qf5 0-1
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Bjornsson, Tomas"]
[Black "Gretarsson, Andri A"]
[Result "1/2-1/2"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 Nbd7 7. Bc4 b5
8. Bd5 Nxd5 9. Nxd5 Bb7 10. Nf5 Nf6 11. Bxf6 gxf6 12. Qd4 Rg8 13. g3 Rg6
14. Nh4 Rh6 15. Nf5 Rg6 16. Nh4 Rh6 17. Nf5 Rg6 18. Nh4 1/2-1/2
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Vidarsson, Jon G"]
[Black "Gislason, Gudmundur"]
[Result "1-0"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 e6 7. f3 b5 8.
g4 h6 9. Rg1 b4 10. Nce2 e5 11. Nb3 d5 12. Ng3 Bb7 13. h4 d4 14. Bf2 Qc7
15. Bd3 Nc6 16. g5 hxg5 17. hxg5 Nd7 18. g6 f6 19. Qe2 Nd8 20. Nf5 Ne6 21.
Bc4 Nf4 22. Bf7+ Kd8 23. Qd2 Rh2 24. O-O-O d3 25. Bb6 Qxb6 26. Qxh2 Rc8 27.
Rd2 a5 28. Kb1 a4 29. Nc1 dxc2+ 30. Rxc2 Rxc2 31. Kxc2 Nc5 32. Rd1+ Kc7 33.
Qd2 Nfe6 34. Kb1 Kb8 35. Nd3 b3 36. Nxc5 Bxc5 37. Ka1 1-0
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Stefansson, Hannes"]
[Black "Olafsson, Helgi"]
[Result "1/2-1/2"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 e6 7. f3 Nbd7 8.
g4 h6 9. Qd2 b5 10. O-O-O b4 11. Nce2 d5 12. Nf4 dxe4 13. Ndxe6 fxe6 14.
Bc4 Qc7 15. Bxe6 Ne5 16. Bb3 Bd7 17. fxe4 Bc5 18. Bxc5 Qxc5 19. Nd3 Nxd3+
20. Qxd3 O-O-O 21. e5 Bb5 22. Qf5+ Nd7 23. Rd5 Qe3+ 24. Kb1 Rhf8 25. Qg6
Nc5 26. Qxg7 Nxb3 27. axb3 Bc6 28. Rxd8+ Rxd8 29. Rf1 Be4 30. Qf6 Qe2 31.
Qe6+ Rd7 32. Rc1 Kc7 33. h4 a5 34. g5 hxg5 35. hxg5 Rd1 36. Qe7+ Kb6 37.
Qe6+ Kc7 38. Qe7+ Kb6 39. Qe6+ Bc6 40. Rxd1 Qxd1+ 41. Ka2 Qxc2 42. Qd6 Qc5
43. Qb8+ Bb7 44. g6 a4 45. Qd8+ Ka7 46. Qd7 Kb6 47. Qd8+ Ka6 48. Qd3+ Ka5
49. Qd8+ Ka6 50. Qd3+ Ka7 51. Qd7 Kb6 1/2-1/2
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.15"]
[Round "7"]
[White "Arnason Jon L"]
[Black "Kristensen Bjarke"]
[Result "0-1"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. a4 Nc6 7. Bc4 Bd7 8.
O-O Rc8 9. Kh1 g6 10. f4 Bg7 11. Nf3 O-O 12. Ba2 b5 13. axb5 axb5 14. Qe1
Nb4 15. Bb3 Nxc2 16. Bxc2 b4 17. e5 dxe5 18. fxe5 Ng4 19. Bd2 bxc3 20. Bxc3
Bb5 21. Rg1 Bc6 22. Bd1 Qc7 23. Ra5 Rcd8 24. Qg3 Ne3 25. Ba4 Bb7 26. Qf2
Rd3 27. Rb1 Ba8 28. Qe2 Ng4 29. Rf1 Re3 30. Qd2 Qc4 31. Qd1 Rd3 32. Qa1
Rxf3 33. Rxf3 Bxf3 34. gxf3 Qf4 35. Qg1 Qxf3+ 36. Qg2 Nf2+ 37. Kg1 Nh3+ 38.
Kh1 Qe3 39. Bd2 Nf2+ 40. Kg1 Qxd2 41. Qxf2 Qc1+ 42. Qf1 Qe3+ 43. Qf2 Qg5+
44. Qg3 Qc1+ 45. Kg2 Rd8 46. Qf3 Qg5+ 47. Qg3 Qf5 0-1
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Bjornsson, Tomas"]
[Black "Gretarsson, Andri A"]
[Result "1/2-1/2"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 Nbd7 7. Bc4 b5
8. Bd5 Nxd5 9. Nxd5 Bb7 10. Nf5 Nf6 11. Bxf6 gxf6 12. Qd4 Rg8 13. g3 Rg6
14. Nh4 Rh6 15. Nf5 Rg6 16. Nh4 Rh6 17. Nf5 Rg6 18. Nh4 1/2-1/2
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Vidarsson, Jon G"]
[Black "Gislason, Gudmundur"]
[Result "1-0"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 e6 7. f3 b5 8.
g4 h6 9. Rg1 b4 10. Nce2 e5 11. Nb3 d5 12. Ng3 Bb7 13. h4 d4 14. Bf2 Qc7
15. Bd3 Nc6 16. g5 hxg5 17. hxg5 Nd7 18. g6 f6 19. Qe2 Nd8 20. Nf5 Ne6 21.
Bc4 Nf4 22. Bf7+ Kd8 23. Qd2 Rh2 24. O-O-O d3 25. Bb6 Qxb6 26. Qxh2 Rc8 27.
Rd2 a5 28. Kb1 a4 29. Nc1 dxc2+ 30. Rxc2 Rxc2 31. Kxc2 Nc5 32. Rd1+ Kc7 33.
Qd2 Nfe6 34. Kb1 Kb8 35. Nd3 b3 36. Nxc5 Bxc5 37. Ka1 1-0
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Stefansson, Hannes"]
[Black "Olafsson, Helgi"]
[Result "1/2-1/2"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 e6 7. f3 Nbd7 8.
g4 h6 9. Qd2 b5 10. O-O-O b4 11. Nce2 d5 12. Nf4 dxe4 13. Ndxe6 fxe6 14.
Bc4 Qc7 15. Bxe6 Ne5 16. Bb3 Bd7 17. fxe4 Bc5 18. Bxc5 Qxc5 19. Nd3 Nxd3+
20. Qxd3 O-O-O 21. e5 Bb5 22. Qf5+ Nd7 23. Rd5 Qe3+ 24. Kb1 Rhf8 25. Qg6
Nc5 26. Qxg7 Nxb3 27. axb3 Bc6 28. Rxd8+ Rxd8 29. Rf1 Be4 30. Qf6 Qe2 31.
Qe6+ Rd7 32. Rc1 Kc7 33. h4 a5 34. g5 hxg5 35. hxg5 Rd1 36. Qe7+ Kb6 37.
Qe6+ Kc7 38. Qe7+ Kb6 39. Qe6+ Bc6 40. Rxd1 Qxd1+ 41. Ka2 Qxc2 42. Qd6 Qc5
43. Qb8+ Bb7 44. g6 a4 45. Qd8+ Ka7 46. Qd7 Kb6 47. Qd8+ Ka6 48. Qd3+ Ka5
49. Qd8+ Ka6 50. Qd3+ Ka7 51. Qd7 Kb6 1/2-1/2

View File

@@ -0,0 +1,2 @@
e4 { This game contains { a nested comment } which should be
handled ok with the --nestedcomment option. } *

View File

@@ -0,0 +1,548 @@
[Event "?"]
[Site "Sarajevo"]
[Date "1972"]
[Round "?"]
[White "Petrosian, Tigran V."]
[Black "Hort"]
[Result "1-0"]
1. Nf3 c5 2. b3 d5 3. e3 Nf6 4. Bb2 e6 5. c4 Nc6 6. cxd5 exd5 7. Be2 Be7 8.
O-O O-O 9. d4 Bg4 10. dxc5 Bxc5 11. Nc3 Rc8 12. Rc1 Be7 13. Nd4 Bxe2 14.
Ncxe2 Qd7 15. Nf4 Rfd8 16. Qd3 Ne4 17. Nxc6 bxc6 18. Rc2 Bf8 19. Rfc1 Qb7
20. Qe2 Re8 21. Qg4 g6 22. Qd1 Bd6 23. Nxd5 Rcd8 24. Rxc6 Qb8 25. f4 Re6
26. Qd4 1-0
[Event "?"]
[Site "Buenos Aires m"]
[Date "1971"]
[Round "6"]
[White "Petrosian, Tigran V."]
[Black "Fischer, Robert J."]
[Result "0-1"]
1. Nf3 c5 2. b3 d5 3. Bb2 f6 4. c4 d4 5. d3 e5 6. e3 Ne7 7. Be2 Nec6 8.
Nbd2 Be7 9. O-O O-O 10. e4 a6 11. Ne1 b5 12. Bg4 Bxg4 13. Qxg4 Qc8 14. Qe2
Nd7 15. Nc2 Rb8 16. Rfc1 Qe8 17. Ba3 Bd6 18. Ne1 g6 19. cxb5 axb5 20. Bb2
Nb6 21. Nef3 Ra8 22. a3 Na5 23. Qd1 Qf7 24. a4 bxa4 25. bxa4 c4 26. dxc4
Nbxc4 27. Nxc4 Nxc4 28. Qe2 Nxb2 29. Qxb2 Rfb8 30. Qa2 Bb4 31. Qxf7+ Kxf7
32. Rc7+ Ke6 33. g4 Bc3 34. Ra2 Rc8 35. Rxc8 Rxc8 36. a5 Ra8 37. a6 Ra7 38.
Kf1 g5 39. Ke2 Kd6 40. Kd3 Kc5 41. Ng1 Kb5 42. Ne2 Ba5 43. Rb2+ Kxa6 44.
Rb1 Rc7 45. Rb2 Be1 46. f3 Ka5 47. Rc2 Rb7 48. Ra2+ Kb5 49. Rb2+ Bb4 50.
Ra2 Rc7 51. Ra1 Rc8 52. Ra7 Ba5 53. Rd7 Bb6 54. Rd5+ Bc5 55. Nc1 Ka4 56.
Rd7 Bb4 57. Ne2 Kb3 58. Rb7 Ra8 59. Rxh7 Ra1 60. Nxd4+ exd4 61. Kxd4 Rd1+
62. Ke3 Bc5+ 63. Ke2 Rh1 64. h4 Kc4 65. h5 Rh2+ 66. Ke1 Kd3 0-1
[Event "?"]
[Site "USSR 26/2"]
[Date "1978"]
[Round "?"]
[White "Petrosian, Tigran V."]
[Black "Balashov,Y"]
[Result "1-0"]
1. b3 e5 2. Bb2 Nc6 3. c4 Nf6 4. e3 d5 5. cxd5 Nxd5 6. a3 Bd6 7. Qc2 O-O 8.
Nf3 Qe7 9. Bd3 Kh8 10. Be4 Nb6 11. Bxc6 bxc6 12. d3 Bd7 13. Nbd2 f5 14. e4
fxe4 15. dxe4 Rf4 16. Qc3 Re8 17. O-O c5 18. Kh1 Bc6 19. Rae1 Nd7 20. Ng1
Nf6 21. f3 Nh5 22. g4 1-0
[Event "?"]
[Site "Tilburg 32/3"]
[Date "1981"]
[Round "?"]
[White "Petrosian, Tigran V."]
[Black "Sosonko,G"]
[Result "1-0"]
1. c4 e5 2. b3 Nf6 3. Bb2 Nc6 4. e3 Be7 5. a3 O-O 6. Qc2 d5 7. cxd5 Nxd5 8.
Nf3 Bf6 9. d3 g6 10. Nbd2 Bg7 11. Rc1 g5 12. Nc4 Qe7 13. b4 a6 14. Nfd2 f5
15. Be2 g4 16. Nb3 Kh8 17. Nca5 Nxa5 18. Nxa5 Qf7 19. O-O c6 20. Nc4 Qe7
21. Rfe1 Bd7 22. Bf1 Nc7 23. Nb6 Rad8 24. Qc5 Qxc5 25. Rxc5 Ne6 26. Rxe5
Bxe5 27. Bxe5+ Kg8 28. d4 Be8 29. Nc4 b5 30. Nd6 Bd7 31. Rc1 Ng5 32. Nb7
Rc8 33. Bd3 Ra8 34. Kf1 Be6 35. Bf4 Nf7 36. Ke2 Bd5 37. Bxf5 Ne5 38. Bxe5
Rxf5 39. Nd6 Rff8 40. e4 Bc4+ 41. Nxc4 bxc4 42. Rxc4 a5 43. Bd6 Rfe8 44. e5
axb4 45. Bxb4 1-0
[Event "Tilburg Grandmaster Tournament"]
[Site "Tilburg, NED"]
[Date "1982.09.??"]
[Round "2"]
[White "Karpov, Anatoly"]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nd2 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Ng5 e6 7. Qe2 Nb6
8. Bb3 a5 9. a3 a4 10. Ba2 h6 11. N5f3 c5 12. c3 Bd7 13. Ne5 cxd4 14. cxd4
Be7 15. Ngf3 O-O 16. O-O Be8 17. Bd2 Nbd5 18. Rfc1 Qb6 19. Bc4 Bc6 20. Re1
Nc7 21. Nxc6 bxc6 22. Bf4 Ncd5 23. Be5 Rfd8 24. Rad1 Bd6 25. Rd2 Bxe5 26.
dxe5 Nd7 27. g3 Nf8 28. Red1 Rd7 29. Qe4 Rb7 30. Rc2 Rab8 31. Rdd2 Ne7 32.
Kg2 Qa5 33. h4 Rd7 34. Be2 Rd5 35. Rd4 Rxd4 36. Qxd4 Nd5 37. Rxc6 Qa8 38.
Rc4 Qb7 39. Rc2 Nb6 40. Bb5 Ng6 41. Qd6 Qa8 42. Bc6 1-0
[Event "?"]
[Site "Moscow"]
[Date "1973.??.??"]
[Round "15"]
[White "Tal,M"]
[Black "Petrosian, Tigran V."]
[Result "0-1"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Ng5 e6 7. Qe2 Nb6
8. Bb3 a5 9. a4 h6 10. N5f3 c5 11. Bf4 Bd6 12. Be5 O-O 13. O-O-O c4 14.
Bxc4 Nxa4 15. Nh3 Nb6 16. g4 a4 17. g5 hxg5 18. Nhxg5 a3 19. b3 Bb4 20.
Rdg1 a2 21. Kb2 Nxc4+ 22. Qxc4 Nd5 23. Ne4 f6 24. Bf4 Ba3+ 25. Ka1 Nxf4 26.
h4 Rf7 27. Rg4 Qa5 0-1
[Event "?"]
[Site "Tilburg"]
[Date "1982.??.??"]
[Round "7"]
[White "Nunn,John"]
[Black "Petrosian,Tigran"]
[Result "1-0"]
1. e4 c6 2. c4 d5 3. exd5 cxd5 4. cxd5 Nf6 5. Nc3 Nxd5 6. Nf3 Nxc3 7. bxc3
g6 8. d4 Bg7 9. Bd3 Nc6 10. O-O O-O 11. Re1 Bg4 12. Be4 Rc8 13. Bg5 Re8 14.
Rb1 Qd7 15. h3 Bxf3 16. Bxf3 b6 17. Bg4 f5 18. Be2 h6 19. Bc1 Kh7 20. d5
1-0
[Event "Bled"]
[Site "?"]
[Date "1961"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Nf3 Ngf6 6. Nxf6+ Nxf6 7. Bc4
Bf5 8. Qe2 e6 9. Bg5 Bg4 10. O-O-O Be7 11. h3 Bxf3 12. Qxf3 Nd5 13. Bxe7
Qxe7 14. Kb1 Rd8 15. Qe4 b5 16. Bd3 a5 17. c3 Qd6 18. g3 b4 19. c4 Nf6 20.
Qe5 c5 21. Qg5 h6 22. Qxc5 Qxc5 23. dxc5 Ke7 24. c6 Rd6 25. Rhe1 Rxc6 26.
Re5 Ra8 27. Be4 Rd6 28. Bxa8 Rxd1+ 29. Kc2 Rf1 30. Rxa5 Rxf2+ 31. Kb3 Rh2
32. c5 Kd8 33. Rb5 Rxh3 34. Rb8+ Kc7 35. Rb7+ Kc6 36. Kc4 1-0
[Event "USSR-World"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Bd3 Nc6 5. c3 Nf6 6. Bf4 Bg4 7. Qb3 Na5
8. Qa4+ Bd7 9. Qc2 e6 10. Nf3 Qb6 11. a4 Rc8 12. Nbd2 Nc6 13. Qb1 Nh5 14.
Be3 h6 15. Ne5 Nf6 16. h3 Bd6 17. O-O Kf8 18. f4 Be8 19. Bf2 Qc7 20. Bh4
Ng8 21. f5 Nxe5 22. dxe5 Bxe5 23. fxe6 Bf6 24. exf7 Bxf7 25. Nf3 Bxh4 26.
Nxh4 Nf6 27. Ng6+ Bxg6 28. Bxg6 Ke7 29. Qf5 Kd8 30. Rae1 Qc5+ 31. Kh1 Rf8
32. Qe5 Rc7 33. b4 Qc6 34. c4 dxc4 35. Bf5 Rff7 36. Rd1+ Rfd7 37. Bxd7 Rxd7
38. Qb8+ Ke7 39. Rde1+ 1-0
[Event "USSR-World"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 g6 4. e5 Bg7 5. f4 h5 6. Nf3 Bg4 7. h3 Bxf3 8.
Qxf3 e6 9. g3 Qb6 10. Qf2 Ne7 11. Bd3 Nd7 12. Ne2 O-O-O 13. c3 f6 14. b3
Nf5 15. Rg1 c5 16. Bxf5 gxf5 17. Be3 Qa6 18. Kf1 cxd4 19. cxd4 Nb8 20. Kg2
Nc6 21. Nc1 Rd7 22. Qd2 Qa5 23. Qxa5 Nxa5 24. Nd3 Nc6 25. Rac1 Rc7 26. Rc3
b6 27. Rgc1 Kb7 28. Nb4 Rhc8 29. Rxc6 Rxc6 30. Rxc6 Rxc6 31. Nxc6 Kxc6 32.
Kf3 1/2-1/2
[Event "?"]
[Site "Bled"]
[Date "1961.??.??"]
[Round "17"]
[White "Keres, Paul"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. N1e2 e6 7. h4 h6 8.
Nf4 Bh7 9. c3 Nf6 10. Bd3 Bxd3 11. Nxd3 Bd6 12. Qf3 Nbd7 13. Bf4 Bxf4 14.
Qxf4 Qb8 15. Qf3 Qd6 16. O-O-O Qd5 17. Qxd5 cxd5 18. f4 Ne4 19. Nxe4 dxe4
20. Ne5 Rd8 21. h5 1/2-1/2
[Event "?"]
[Site "Piatgorsky Cup"]
[Date "1963.??.??"]
[Round "1"]
[White "Keres, Paul"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Bc4 e6 7. N1e2 Nf6
8. Nf4 Bd6 9. Bb3 Nbd7 10. Qf3 Qc7 11. h4 O-O-O 12. h5 Bf5 13. Nxf5 Qa5+
14. c3 Qxf5 15. Qd3 Qxd3 16. Nxd3 h6 17. Rh4 Rhe8 18. Be3 Nd5 19. O-O-O
Nxe3 20. fxe3 Nf6 21. Rf1 Re7 22. Nf2 Bg3 23. Rh3 Bd6 24. Bc2 e5 25. Nd3
exd4 26. exd4 Re2 27. g4 Rde8 28. Bd1 R2e3 29. Rxe3 Rxe3 30. Rf3 1/2-1/2
[Event "?"]
[Site "Moscow-Wch"]
[Date "1966.??.??"]
[Round "1"]
[White "Spassky, Boris"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 h6 7. Nf3 Nd7 8.
Bd3 Bxd3 9. Qxd3 Qc7 10. Bd2 e6 11. O-O-O O-O-O 12. c4 Ngf6 13. Kb1 c5 14.
Bc3 cxd4 15. Nxd4 a6 16. Nf3 Bc5 17. Qe2 Bd6 18. Ne4 Be7 19. Nxf6 Bxf6 20.
Bxf6 Nxf6 21. Ne5 Rxd1+ 22. Rxd1 Rd8 23. Rxd8+ Kxd8 24. Qd3+ Ke7 25. Qd4 h5
26. a3 Nd7 27. Nxd7 Qxd7 28. Qc5+ Qd6 29. Qg5+ Ke8 30. Qe3 Qc6 31. Qg3 g6
32. b3 Qe4+ 33. Kb2 e5 34. Qe3 Qxg2 35. Qxe5+ Kf8 36. Qh8+ Ke7 37. Qe5+
1/2-1/2
[Event "?"]
[Site "Moscow-Wch"]
[Date "1966.??.??"]
[Round "3"]
[White "Spassky, Boris"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 6. Nf3 Be7 7. cxd5 Nxd5
8. Bc4 Nf6 9. O-O O-O 10. Qe2 Nc6 11. Be3 Na5 12. Bd3 b6 13. Bg5 Bb7 14.
Rad1 Rc8 15. Rfe1 h6 16. Bc1 Bb4 17. Bd2 Bxc3 18. bxc3 Qd5 19. Qf1 Qxa2 20.
Ne5 Nb3 21. Re2 Nxd2 22. Rexd2 Qd5 23. c4 Qd6 24. Qe2 Rfd8 25. h3 Nd7 26.
Ng4 h5 27. Ne3 g6 28. Ra2 Ra8 29. Qc2 Kg7 30. Be4 Bxe4 31. Qxe4 Nf6 32. Qh4
Rd7 33. Rad2 Rad8 34. Rd3 a6 35. Qg5 Ne4 36. Qh4 Nf6 37. Rb3 Qc7 38. d5 Qe5
39. Rxb6 exd5 40. Nxd5 Nxd5 41. cxd5 Rxd5 42. Qxd8 Rxd8 43. Rxd8 Qe1+
1/2-1/2
[Event "?"]
[Site "Moscow-Wch"]
[Date "1966.??.??"]
[Round "5"]
[White "Spassky, Boris"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 g6 6. Qb3 Bg7 7. cxd5 O-O
8. g3 Na6 9. Bg2 Qb6 10. Qxb6 axb6 11. Nge2 Nb4 12. O-O Rd8 13. d6 Rxd6 14.
Bf4 Rd7 15. Rfd1 Nbd5 16. Be5 Bh6 17. a3 e6 18. Nxd5 Nxd5 19. Rd3 Bg5 20.
Bxd5 exd5 21. h4 Bd8 22. Rc1 Re7 23. Nf4 Be6 24. Rdc3 Bd7 25. Nxd5 Re6 26.
Bc7 Kg7 27. Bxd8 Rxd8 28. Ne3 b5 29. d5 Rb6 30. Nc2 h6 31. Nb4 g5 32. hxg5
hxg5 33. Kg2 Rf6 34. Re3 Rh8 35. Nd3 Rd6 36. Ne5 Bh3+ 37. Kf3 Rxd5 38. Rc7
Be6 39. Rxb7 Rc5 40. Ra7 Bd5+ 41. Kg4 Rc2 42. Kxg5 Rxf2 43. Nd3 Rf3 44.
Rae7 Rxe3 45. Rxe3 f6+ 46. Kf4 Kf7 47. Nb4 Bc4 48. Rc3 Rh2 49. b3 Be6 50.
Nd3 Ra2 51. Rc7+ Kg6 52. Nc5 Bf7 53. Rb7 Rxa3 54. Rxb5 Ra1 55. Ne4 Rf1+ 56.
Ke3 Re1+ 57. Kf3 Rf1+ 58. Ke2 Rb1 59. Nd2 Rg1 60. Kf2 Rc1 61. b4 Rc2 62.
Ke3 Rc3+ 63. Kf4 Rd3 64. Nf3 Bd5 65. Nh4+ Kf7 66. Rb8 Rd4+ 67. Ke3 Re4+ 68.
Kf2 Ke7 69. Ng6+ Kd7 70. Nf4 Bc6 71. Nd3 Kc7 72. Rf8 Bb5 73. Nf4 Kd7 74.
Rf7+ Ke8 75. Rb7 Rxb4 76. Nd5 Rb2+ 77. Ke3 Rb3+ 78. Kf4 Bc4 79. Nxf6+ Kf8
1/2-1/2
[Event "?"]
[Site "Moscow-Wch"]
[Date "1966.??.??"]
[Round "9"]
[White "Spassky, Boris"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 6. Nf3 Be7 7. cxd5 Nxd5
8. Bd3 Nc6 9. O-O O-O 10. Re1 Bf6 11. Be4 Nce7 12. Qc2 g6 13. Bh6 Bg7 14.
Bg5 f6 15. Bd2 Bd7 16. Qb3 Bc6 17. Bxd5 exd5 18. Ne4 Rf7 19. Nc5 Nf5 20. h3
Bf8 21. Ne6 Qd7 22. Nxf8 Rfxf8 23. Bb4 Rfe8 24. Rxe8+ Rxe8 25. Re1 Rxe1+
26. Bxe1 1/2-1/2
[Event "?"]
[Site "Moscow-Wch"]
[Date "1966.??.??"]
[Round "13"]
[White "Spassky, Boris"]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 h6 7. Nf3 Nd7 8.
h5 Bh7 9. Bd3 Bxd3 10. Qxd3 Qc7 11. Bd2 e6 12. Qe2 Ngf6 13. O-O-O O-O-O 14.
Ne5 Nxe5 15. dxe5 Nd7 16. f4 Be7 17. Ne4 Nc5 18. Nc3 f6 19. exf6 Bxf6 20.
Qc4 Qb6 21. b4 Na6 22. Ne4 Nc7 23. Rhe1 Rd4 24. Qb3 Qb5 25. c3 Rxe4 26.
Rxe4 Qxh5 27. Qc4 Qf5 28. Qe2 h5 29. Be1 Re8 30. g3 a5 31. bxa5 Qxa5 32.
Qc2 Qf5 33. Ra4 g5 34. fxg5 Bxg5+ 35. Kb1 Qxc2+ 36. Kxc2 e5 37. Re4 Nd5 38.
Bf2 Nf6 39. Ra4 Kc7 40. Bc5 Nd5 41. Re4 b6 42. Bg1 Bd8 43. Rf1 Nf6 44. Re2
c5 45. Rf5 Kd6 46. a4 Kd5 47. Kd3 Ng4 48. Rb2 Rh8 49. a5 c4+ 50. Ke2 Ke4
51. Rf7 bxa5 52. Rb8 a4 53. Rc8 Bf6 54. Rxc4+ Kf5 55. Ra7 a3 56. Rxa3 Rb8
57. Rb4 Rc8 58. c4 Be7 59. c5 e4 60. Ra7 Bf6 61. Rh7 Kg6 62. Rd7 Kf5 63.
Rd5+ Be5 64. Rb6 e3 65. Kf3 Nf6 66. Rd3 Rxc5 67. Bxe3 Rc2 68. Rd8 Rc3 69.
Ke2 Rc2+ 70. Kd1 Rc3 71. Bf2 Ne4 72. Rf8+ Kg5 73. Rb5 Rd3+ 74. Ke2 Rd5 75.
Rxd5 Nc3+ 76. Kf3 Nxd5 77. Ra8 Kf5 78. Ra5 Ke6 79. Be1 Nf6 80. Rb5 Nd5 81.
Bd2 Bg7 82. Bc1 Be5 83. Bb2 Bc7 84. Rc5 Bd6 85. Rc1 Ne7 86. Re1+ Kf5 87.
Ra1 Nc6 88. Ra6 Be5 89. Rxc6 Bxb2 90. Rc5+ Kg6 91. Kf4 1-0
[Event "?"]
[Site "URS"]
[Date "1966.??.??"]
[Round "?"]
[White "Tal, Mikhail N."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 6. Nf3 Be7 7. cxd5 Nxd5
8. Bc4 O-O 9. O-O Nc6 10. Re1 Bf6 11. Ne4 b6 12. a3 Bb7 13. Qd3 Rc8 14.
Nfg5 Bxg5 15. Bxg5 f6 16. Bd2 Qd7 17. Rad1 Nce7 18. Ba2 Rfe8 19. Bb1 Ng6
20. Qg3 f5 21. Qd6 Rcd8 22. Qxd7 Rxd7 23. Ng5 Rde7 24. Ba2 h6 25. Nf3 Rc7
26. Rc1 Rxc1 27. Rxc1 Rc8 28. Rxc8+ Bxc8 29. h4 Bb7 1/2-1/2
[Event "Moskva tt"]
[Site "?"]
[Date "1961.??.??"]
[Round "?"]
[White "Tal, Mikhail N."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nf3 Nd7 7. Bc4 e6
8. O-O Ngf6 9. Ng5 h6 10. Nh3 Bd6 11. Nf4 Bxf4 12. Bxf4 Nd5 13. Bc1 Qh4 14.
Bd3 Bxd3 15. Qxd3 O-O-O 16. Rd1 N7f6 17. c4 Nc7 18. b4 Rd7 19. Bb2 Rhd8 20.
Qe2 Qg4 21. f3 Qg6 22. a4 h5 23. b5 h4 24. bxc6 bxc6 25. Ne4 Nxe4 26. fxe4
h3 27. g3 f5 28. e5 c5 29. dxc5 Rxd1+ 30. Rxd1 Rxd1+ 31. Qxd1 Qe8 32. Qd6
Kb7 33. c6+ Qxc6 34. Qxc6+ Kxc6 35. Bd4 a5 36. Bc3 Na6 37. Bxa5 Nc5 38. Bb4
Nxa4 39. g4 fxg4 40. Kf2 Nb2 41. Kg3 Nxc4 42. Kxg4 Nxe5+ 43. Kxh3 Kd5 44.
Kh4 Kc4 45. Bd6 Nf7 46. Bc7 g6 47. Kg4 Kd5 48. h4 Ke4 49. h5 Ne5+ 1/2-1/2
[Event "URS-ch"]
[Site "?"]
[Date "1973.??.??"]
[Round "?"]
[White "Tal, Mikhail N."]
[Black "Petrosian, Tigran V."]
[Result "0-1"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Ng5 e6 7. Qe2 Nb6
8. Bb3 a5 9. a4 h6 10. N5f3 c5 11. Bf4 Bd6 12. Be5 O-O 13. O-O-O c4 14.
Bxc4 Nxa4 15. Nh3 Nb6 16. g4 a4 17. g5 hxg5 18. Nhxg5 a3 19. b3 Bb4 20.
Rhg1 a2 21. Kb2 Nxc4+ 22. Qxc4 Nd5 23. Ne4 f6 24. Bf4 Ba3+ 25. Ka1 Nxf4 26.
h4 Rf7 27. Rg4 Qa5 0-1
[Event "?"]
[Site "Moscow"]
[Date "1973.??.??"]
[Round "2"]
[White "Petrosian, Tigran V."]
[Black "Kuzmin,G"]
[Result "1/2-1/2"]
1. c4 Nf6 2. d4 e6 3. Nc3 Bb4 4. e3 c5 5. Bd3 O-O 6. Nf3 d5 7. O-O dxc4 8.
Bxc4 a6 9. a3 Ba5 10. dxc5 Bxc3 11. bxc3 Qa5 12. a4 Nbd7 13. c6 bxc6 14.
Qc2 c5 15. e4 Qc7 16. Re1 Ng4 17. Kh1 Re8 18. h3 Ngf6 19. e5 Nd5 20. Ng5
Nf8 21. f4 Bb7 22. Ne4 Ng6 23. Qf2 Nb6 24. Bf1 Bxe4 25. Rxe4 Qc6 26. Qc2
Nd5 27. a5 Red8 28. Kh2 Rab8 29. Rea4 Nge7 30. Bd3 Nf5 31. Bxf5 exf5 32.
Qxf5 Nxc3 33. Rc4 1/2-1/2
[Event "?"]
[Site "Moscow"]
[Date "1973.??.??"]
[Round "10"]
[White "Petrosian, Tigran V."]
[Black "Smyslov,V"]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 c5 5. Bd3 b6 6. Ne2 Nc6 7. O-O cxd4 8.
exd4 Bb7 9. d5 Ne5 10. Bf4 Nxd3 11. Qxd3 exd5 12. cxd5 O-O 13. a3 Bxc3 14.
Nxc3 Re8 15. Bd6 Ng4 16. Qg3 Nh6 17. Rfe1 Nf5 18. Qf4 Qf6 19. Be5 Qg6 20.
Qa4 a6 21. Bf4 b5 22. Qb4 Rec8 23. Qe4 h5 24. Qd3 Rc4 25. Re4 Nh4 26. Bg3
Rxe4 27. Nxe4 Nxg2 28. Kxg2 h4 29. Rd1 hxg3 30. hxg3 Rc8 31. f3 f5 1/2-1/2
[Event "?"]
[Site "Tilburg"]
[Date "1982.??.??"]
[Round "10"]
[White "Petrosian,Tigran"]
[Black "Browne,Walter"]
[Result "1-0"]
1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. Nc3 Bb4 5. e3 O-O 6. Bd3 Bb7 7. O-O d5 8.
a3 Bd6 9. cxd5 exd5 10. b4 a6 11. Qb3 Qe7 12. Rb1 Nbd7 13. a4 Ne4 14. Bb2
Ndf6 15. b5 a5 16. Rbd1 Nxc3 17. Bxc3 Ne4 18. Bb2 Rad8 19. Ne5 Kh8 20. Qc2
f6 21. Nf3 Bc8 22. Ne1 f5 23. g3 Rf6 24. Nf3 Rdf8 25. Ne5 Rh6 26. f3 Ng5
27. Qg2 Nh3+ 28. Kh1 g5 29. g4 Qf6 30. Rd2 Rh4 31. Rc2 Qg7 32. gxf5 Bxf5
33. Bxf5 Rxf5 34. Bc3 Rh6 35. Ng4 Rh5 36. Be1 Qe7 37. Bg3 Rf7 38. Rfc1 Kg7
39. Rc6 Kf8 40. Bxd6 cxd6 41. Qg3 Rh4 42. Qxd6 1-0
[Event "?"]
[Site "Lone"]
[Date "1978.??.??"]
[Round "?"]
[White "Portisch, Lajos"]
[Black "Petrosian, Tigran"]
[Result "0-1"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 b6 5. Bd3 Bb7 6. Nf3 O-O 7. O-O d5 8.
a3 Bd6 9. b4 dxc4 10. Bxc4 Nbd7 11. Bb2 a5 12. b5 e5 13. Re1 e4 14. Nd2 Qe7
15. Be2 Rad8 16. Qc2 Rfe8 17. f3 exf3 18. Bxf3 Bxf3 19. Nxf3 Ne4 20. Nxe4
Qxe4 21. Qxe4 Rxe4 22. Nd2 Ree8 23. e4 Nc5 24. Nc4 Nxe4 25. Rac1 Bf8 26.
Ne5 Nd6 27. a4 f6 28. Nf3 Rxe1+ 29. Nxe1 Rd7 30. Nf3 Nf5 31. Kf2 h5 32. Rc2
g5 33. Rc4 Bd6 34. g3 Kf7 35. Ng1 Ne7 36. Ne2 Nd5 37. Bc1 Kg6 38. Rc2 Kf5
39. Kf3 g4+ 40. Kf2 Rh7 41. Rd2 h4 42. Kg2 Ke4 43. Rd1 Ne3+ 44. Bxe3 Kxe3
45. Nc3 h3+ 0-1
[Event "?"]
[Site "Milano"]
[Date "1975.??.??"]
[Round "1"]
[White "Petrosian, Tigran"]
[Black "Karpov, Anatoly"]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Bd3 c5 6. Nf3 d5 7. O-O cxd4 8.
exd4 dxc4 9. Bxc4 b6 10. Bg5 Bb7 11. Qe2 Bxc3 12. bxc3 Nbd7 13. Bd3 Qc7 14.
c4 Ng4 15. Be4 Bxe4 16. Qxe4 Ngf6 17. Qd3 h6 18. Bxf6 Nxf6 19. a4 Rac8 20.
Rfc1 Rfd8 21. h3 e5 22. Nxe5 Qxe5 23. dxe5 Rxd3 24. exf6 Rd4 25. a5 gxf6
26. axb6 axb6 27. Rab1 Rcxc4 28. Rxc4 Rxc4 29. Rxb6 1/2-1/2
[Event "?"]
[Site "Moscow"]
[Date "1971.??.??"]
[Round "1"]
[White "Petrosian, Tigran"]
[Black "Kortchnoi, Viktor"]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. cxd5 exd5 6. a3 Bxc3+ 7. bxc3
O-O 8. Bg5 c5 9. e3 Nbd7 10. Bd3 Qa5 11. Ne2 b6 12. O-O Ba6 13. Bxa6 Qxa6
14. Bxf6 Nxf6 15. Nf4 Qc4 16. Qa2 Qxa2 17. Rxa2 Rac8 18. a4 Rfd8 19. Rb1
Ne4 20. Ne2 Nd6 21. h4 Nc4 22. Nf4 Kf8 23. g4 g6 24. Kg2 h6 25. Rd1 g5 26.
hxg5 hxg5 27. Ne2 Nd6 28. Ng3 cxd4 29. Rxd4 Ne4 30. Nxe4 dxe4 31. Rxe4 Rxc3
32. a5 Rdc8 33. axb6 axb6 34. Rb2 R3c4 35. Rxc4 Rxc4 1/2-1/2
[Event "?"]
[Site "Wch"]
[Date "1963.??.??"]
[Round "?"]
[White "Petrosian, Tigran V."]
[Black "Botvinnik, Mikhail"]
[Result "0-1"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. cxd5 exd5 6. Bg5 h6 7. Bxf6 Qxf6
8. a3 Bxc3+ 9. Qxc3 c6 10. e3 O-O 11. Ne2 Re8 12. Ng3 g6 13. f3 h5 14. Be2
Nd7 15. Kf2 h4 16. Nf1 Nf8 17. Nd2 Re7 18. Rhe1 Bf5 19. h3 Rae8 20. Nf1 Ne6
21. Qd2 Ng7 22. Rad1 Nh5 23. Rc1 Qd6 24. Rc3 Ng3 25. Kg1 Nh5 26. Bd1 Re6
27. Qf2 Qe7 28. Bb3 g5 29. Bd1 Bg6 30. g4 hxg3 31. Nxg3 Nf4 32. Qh2 c5 33.
Qd2 c4 34. Ba4 b5 35. Bc2 Nxh3+ 36. Kf1 Qf6 37. Kg2 Nf4+ 38. exf4 Rxe1 39.
fxg5 Qe6 40. f4 Re2+ 0-1
[Event "?"]
[Site "Curacao ct"]
[Date "1962.??.??"]
[Round "3"]
[White "Petrosian, Tigran V."]
[Black "Keres, Paul"]
[Result "1/2-1/2"]
1. c4 Nf6 2. d4 e6 3. Nf3 b6 4. Nc3 Bb4 5. e3 c5 6. Bd3 d5 7. dxc5 bxc5 8.
O-O O-O 9. Ne2 Bb7 10. b3 Nbd7 11. Bb2 Qe7 12. Ng3 g6 13. cxd5 exd5 14. a3
Ba5 15. b4 cxb4 16. Qa4 Bb6 17. axb4 Ng4 18. Rfe1 Nde5 19. Nxe5 Nxe5 20.
Rad1 Nxd3 21. Rxd3 Rfc8 22. b5 1/2-1/2
[Event "?"]
[Site "Moscow-Wch"]
[Date "1966.??.??"]
[Round "20"]
[White "Petrosian, Tigran V."]
[Black "Spassky, Boris"]
[Result "1-0"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Bd3 c5 6. Nf3 d5 7. O-O Nc6 8.
a3 Bxc3 9. bxc3 dxc4 10. Bxc4 Qc7 11. Bd3 e5 12. Qc2 Bg4 13. Nxe5 Nxe5 14.
dxe5 Qxe5 15. f3 Bd7 16. a4 Rfe8 17. e4 c4 18. Be2 Be6 19. Be3 Qc7 20. Rab1
Nd7 21. Rb5 b6 22. Rfb1 Qc6 23. Bd4 f6 24. Qa2 Kh8 25. Bf1 h6 26. h3 Rab8
27. a5 Rb7 28. axb6 axb6 29. Qf2 Ra8 30. Qb2 Rba7 31. Bxb6 Ra2 32. Qb4 Rc2
33. Bf2 Qc7 34. Qe7 Bxh3 35. gxh3 Rxf2 36. Kxf2 Qh2+ 37. Bg2 Ne5 38. Rb8+
Rxb8 39. Rxb8+ Kh7 40. Rd8 Ng6 41. Qe6 1-0
[Event "?"]
[Site "Moscow-Wch"]
[Date "1969.??.??"]
[Round "10"]
[White "Petrosian, Tigran V."]
[Black "Spassky, Boris"]
[Result "1-0"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Bd3 b6 6. Ne2 d5 7. O-O dxc4 8.
Bxc4 Bb7 9. f3 c5 10. a3 cxd4 11. axb4 dxc3 12. Nxc3 Nc6 13. b5 Ne5 14. Be2
Qc7 15. e4 Rfd8 16. Qe1 Qc5+ 17. Qf2 Qe7 18. Ra3 Ne8 19. Bf4 Ng6 20. Be3
Nd6 21. Rfa1 Nc8 22. Bf1 f5 23. exf5 exf5 24. Ra4 Re8 25. Bd2 Qc5 26. Qxc5
bxc5 27. Rc4 Re5 28. Na4 a6 29. Nxc5 axb5 30. Nxb7 Rxa1 31. Rxc8+ Kf7 32.
Nd8+ Ke7 33. Nc6+ Kd7 34. Nxe5+ Kxc8 35. Nxg6 hxg6 36. Bc3 Rb1 37. Kf2 b4
38. Bxg7 1-0
[Event "?"]
[Site "Milano"]
[Date "1975.??.??"]
[Round "2"]
[White "Ljubojevic, Ljubomir"]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. a3 Be7 6. Nf3 O-O 7. e3 b6 8.
cxd5 exd5 9. b4 Re8 10. Bd3 Bb7 11. O-O Bd6 12. Bb2 a6 13. Ne5 c5 14. bxc5
bxc5 15. Rab1 Qc7 16. h3 c4 1/2-1/2
[Event "32nd ol"]
[Site "Yerevan ARM"]
[Date "1996.09.17"]
[Round "02"]
[White "Gostisa,L"]
[Black "Petrosian,A"]
[Result "1/2-1/2"]
1. d4 Nf6 2. Nf3 e6 3. g3 d5 4. Bg2 Nbd7 5. O-O b5 6. b3 Bb7 7. c4 bxc4 8.
bxc4 dxc4 9. Qa4 c5 10. Ba3 Qc7 11. Qxc4 Rc8 12. Rc1 Qb8 1/2-1/2
[Event "?"]
[Site "Belgrade"]
[Date "1954.??.??"]
[Round "?"]
[White "Janosevic"]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 e6 5. Nc3 Nf6 6. Bg5 Be7 7. Nf3 O-O 8.
Rc1 a6 9. cxd5 exd5 10. Be2 Nc6 11. Ne5 Na5 12. O-O h6 13. Bh4 Bf5 14. Bf3
Be6 15. Re1 Nc6 16. Ng6 fxg6 17. Rxe6 g5 18. Bg3 Qd7 19. Re1 Rae8 20. Be5
Kh8 21. Qb3 g4 22. Bxd5 Nxd5 23. Nxd5 Bg5 24. Rcd1 Na5 25. Nb6 Qd8 26. Qa4
Qxb6 27. Bxg7+ Kxg7 28. Rxe8 Nc6 29. Rxf8 Kxf8 30. d5 Ne5 31. d6 Qxb2 32.
d7 Nf7 33. Qxg4 Qxa2 34. Qb4+ Be7 35. d8=Q+ Nxd8 36. Rxd8+ Kf7 37. Qf4+ Kg7
38. Qg4+ Kf6 39. Rd1 b5 40. h4 Qe6 41. Qh5 Kg7 42. Rd3 Bd6 43. Qd1 Bc5 44.
Rg3+ Kf6 45. Qa1+ Kf5 46. Qb1+ Ke5 47. Rg6 Qf7 48. Qe1+ Kd5 49. Rxa6 Qf4
50. Qd1+ Kc4 51. Ra2 Bd4 52. Qe2+ Kb4 53. Qe1+ Kb3 54. Qb1+ Kc4 55. Rc2+
Bc3 56. Re2 Bd4 57. Qc2+ Kd5 58. Qb3+ Kc5 59. g3 Qf6 60. Rc2+ Kb6 61. Kg2
Qf5 62. Re2 Kc5 63. Qc2+ Qxc2 64. Rxc2+ Kd5 65. f4 b4 66. Kf3 b3 67. Rc1 b2
68. Rd1 h5 69. g4 hxg4+ 70. Kxg4 Ke4 71. h5 Be3 72. Rb1 Bc1 73. h6 Bxf4 74.
Re1+ 1-0
[Event "YUG-URS"]
[Site "Belgrade"]
[Date "1956.??.??"]
[Round "?"]
[White "Pirc, Vasja"]
[Black "Petrosian, Tigran V"]
[Result "1/2-1/2"]
1. Nf3 c5 2. c4 Nc6 3. g3 g6 4. Bg2 Bg7 5. O-O Nh6 6. Nc3 O-O 7. d3 d6 8.
Bd2 Nf5 9. a3 a6 10. Rb1 Rb8 11. b4 cxb4 12. axb4 b5 13. cxb5 axb5 14. e3
e5 15. Qe2 d5 16. Rfc1 Nfe7 17. Be1 h6 18. Nd2 d4 19. Nce4 19...
Kh7 20. Nb3 f5 21. Nec5 dxe3 22. fxe3 f4 23. Na5 Rb6 24. Ncb3 Bd7 25. exf4
exf4 26. Bf2 fxg3 27. hxg3 Ne5 28. Nb7 Rxb7 29. Bxb7 Bg4 30. Qf1 Nf3+ 31.
Bxf3 Rxf3 32. Re1 Nf5 33. Qg2 Qd5 34. Nd2 Nd4 35. Re7 Qd6 36. Re4 h5 37.
Re3 Rxe3 38. Bxe3 Ne2+ 39. Kf2 Nc3 40. Re1 Qxd3 41. Qf1 Qd6 42. Kg2 Qxb4
43. Qf7 1/2-1/2
[Event "Bled"]
[Site "Bled"]
[Date "1961.09.09"]
[Round "5"]
[White "Germek, Milan"]
[Black "Petrosian, Tigran V"]
[Result "0-1"]
1. d4 Nf6 2. c4 d6 3. Nc3 e5 4. dxe5 dxe5 5. Qxd8+ Kxd8 6. Nf3 Nbd7 7. Bg5
c6 8. O-O-O Kc7 9. Bh4 Bb4 10. Kc2 Re8 11. Bg3 Nh5 12. Nd2 f5 13. e3 Nxg3
14. hxg3 Nf6 15. a3 Bf8 16. Be2 a5 17. Rde1 e4 18. Nb3 a4 19. Nd4
19... Re5 20. Kb1 Rc5 21. Rc1 g6 22. Ka1 h5 23. Rhd1 Re5 24. Rd2 Nd7 25.
Bd1 Nc5 26. Be2 Be6 27. Kb1 Rd8 28. Rh1 Bf7 29. Rc1 Nd7 30. Ka1 Rc5 31. Nb1
Bg7 32. Rdc2 Ra5 33. Rd1 Rh8 34. Nd2 Nc5 35. Kb1 h4 36. g4 f4 37. Nf1 h3
38. gxh3 f3 0-1

View File

@@ -0,0 +1,8 @@
% Output the tags of the seven tag roster alphabetically.
Black
Date
Event
Result
Round
Site
White

View File

@@ -0,0 +1,3 @@
White "Fischer"
Black "Petrosian"
Date "1970"

View File

@@ -0,0 +1,27 @@
[Event "?"]
[Site "Biel SKA (5)"]
[Date "1995.??.??"]
[Round "?"]
[White "Adianto,U"]
[Black "Gelfand,B"]
[Result "1-0"]
[WhiteElo "2590"]
[BlackElo "2685"]
[ECO "E63"]
[PlyCount "166"]
1. d4 Nf6 2. c4 g6 3. g3 Bg7 4. Bg2 O-O 5. Nf3 d6 6. O-O Nc6 7. Nc3 a6 8.
h3 Bd7 9. e4 e5 10. d5 Nd4 11. Nxd4 exd4 12. Qxd4 Qc8 13. h4 b5 14. cxb5
axb5 15. Qb4 Ng4 16. Bf4 Re8 17. Rac1 Qb8 18. Bh3 Qb6 19. Bxg4 Bxg4 20.
Qxb5 Reb8 21. Qxb6 Rxb6 22. b3 c5 23. dxc6 Rxc6 24. Nd5 Rxc1 25. Rxc1 Rxa2
26. Kg2 Bd4 27. Be3 Bxe3 28. Nxe3 Be6 29. Rb1 Bd7 30. g4 Bb5 31. Kg3 Bd3
32. Rd1 Bxe4 33. Rxd6 Rb2 34. Rb6 Kg7 35. g5 h6 36. b4 hxg5 37. hxg5 Kf8
38. f3 Bd3 39. Kf4 Ke8 40. Ke5 Re2 41. Kd4 Bb1 42. b5 Rf2 43. Rb8+ Kd7 44.
Rb7+ Ke6 45. Rb6+ Kd7 46. Rf6 Rd2+ 47. Kc5 Ba2 48. Nc4 Rg2 49. Rxf7+ Ke6
50. Rf4 Rxg5+ 51. Kc6 Bb3 52. Re4+ Kf6 53. Ne3 Be6 54. b6 Bc8 55. Nd5+ Kg7
56. Nb4 Rg1 57. Rc4 Re1 58. Kc7 Re8 59. Re4 Rf8 60. Nc6 Ba6 61. Re3 Kh6 62.
Ra3 Rf7+ 63. Kd6 Rf6+ 64. Ke7 Rxc6 65. Rxa6 Kh7 66. Kd8 Kh6 67. Ke7 Kh7 68.
Kd7 Rf6 69. b7 Rxa6 70. b8=Q Ra5 71. Ke6 Rf5 72. Qg3 Kg7 73. Qg4 Rf6+ 74.
Ke5 Rf7 75. Ke4 Kh7 76. Qc8 Kg7 77. Ke3 Rf8 78. Qc3+ Kh7 79. Kf2 Rf5 80.
Kg3 Rg5+ 81. Kf4 Rf5+ 82. Kg4 Rf7 83. Qe5 1-0

View File

@@ -0,0 +1,18 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {Time control} 1/2-1/2

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
{ diagram } 28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7
31. Kd4 Kd6 32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {
Time control } 1/2-1/2

View File

@@ -0,0 +1,18 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {Time control} 1/2-1/2

View File

@@ -0,0 +1,6 @@
:-t
% Find a supported Knight on e4.
FENPattern "*/*/*/*/???pN???/???P????/*/*"
% Find a supported Knight for White on d4
% or Black on d5.
FENPatternI "*/*/*/*/???Np???/????P???/*/*" Nd4th

View File

@@ -0,0 +1,9 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4 Qh4# 0-1

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,188 @@
[Event "?"]
[Site "Wch"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 Ne4 6. Qc2 f5 7. Nh3 O-O
8. f3 Nf6 9. c5 b6 10. cxb6 cxb6 11. e3 Qc7 12. Bd2 Ne8 13. c4 Ba6 14. Rc1
Nd6 15. Qa4 Qc6 16. Qxc6 Nxc6 17. Bb4 Nxb4 18. axb4 Bxc4 19. Bxc4 Rfc8 20.
Bxe6+ dxe6 21. Ke2 Kf7 22. Nf4 a5 23. bxa5 bxa5 24. Kd3 a4 25. Rxc8 Rxc8
26. Ra1 Nc4 27. Rb1 a3 28. Rb7+ Kf6 29. Ra7 g5 30. Nh5+ Kg6 31. g4 Nb2+ 32.
Kd2 Nc4+ 33. Kd3 Nb2+ 34. Kd2 Nc4+ 35. Ke2 Rc6 36. h3 e5 37. dxe5 fxg4 38.
hxg4 Nxe5 39. Rxa3 Rc2+ 40. Kf1 Kf7 41. e4 Rd2 42. Ke1 Rg2 43. Rb3 Ke7 44.
Ng7 Nxf3+ 45. Rxf3 Rxg4 46. Nf5+ Ke6 47. Ng3 h5 48. Nxh5 Rxe4+ 49. Kf2 Ke5
50. Kg3 Rh4 51. Ng7 Rf4 52. Ra3 Rd4 53. Ra6 Rd6 54. Ra7 Rd4 55. Rf7 Rf4 56.
Re7+ Kf6 57. Ra7 Re4 58. Nh5+ Kg6 59. Kf3 Rb4 60. Ng3 Rf4+ 61. Ke3 Rf7 62.
Ra5 Rf6 63. Ne4 Rf5 64. Ra6+ Kg7 65. Ng3 Re5+ 66. Kd4 Rb5 67. Ke4 Kf7 68.
Nf5 Rb4+ 69. Nd4 Rb1 70. Nf3 Rb4+ 71. Nd4 Rb1 72. Nc6 Kg6 73. Ne5+ Kh5 74.
Ra5 Re1+ 75. Kf3 Rf1+ 76. Kg3 Rf5 1/2-1/2
[Event "?"]
[Site "Wch"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 Ne4 6. Qc2 f5 7. Nh3 d6
8. f3 Nf6 9. e4 fxe4 10. fxe4 e5 11. Nf2 O-O 12. Be2 c5 13. dxc5 dxc5 14.
O-O Nc6 15. Bg5 Qe8 16. Nd1 Qg6 17. Bxf6 Rxf6 18. Ne3 Rxf1+ 19. Rxf1 Be6
20. Qd3 Rd8 21. Nd5 Rf8 22. Nc7 Rxf1+ 23. Bxf1 Qf7 24. Qd6 Bc8 25. Na6 Qf4
26. Qd5+ Kh8 27. Qxc5 Be6 28. Nc7 Bg8 29. Qf2 Qxe4 30. Ne8 Qg6 31. Qf8 e4
32. Nd6 Ne5 33. c5 Nd3 34. Nf5 Ne5 35. Ne7 Qf7 36. Qxf7 Bxf7 37. Kf2 Bc4
38. Bxc4 Nxc4 39. c6 bxc6 40. Nxc6 a5 41. a4 1/2-1/2
[Event "?"]
[Site "Wch"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 Ne4 6. e3 f5 7. Qh5+ g6
8. Qh6 d6 9. f3 Nf6 10. e4 e5 11. Bg5 Qe7 12. Bd3 Rf8 13. Ne2 Qf7 14. Qh4
fxe4 15. fxe4 Ng4 16. h3 Qf2+ 17. Kd2 Qxh4 18. Bxh4 Nf2 19. Rhf1 Nxd3 20.
Rxf8+ Kxf8 21. Kxd3 Be6 22. Ng3 Nd7 23. Nf1 a6 24. Bf2 Kg7 25. Nd2 Rf8 26.
Be3 b6 27. Rb1 Nf6 1/2-1/2
[Event "?"]
[Site "Wch"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 O-O 6. f3 d5 7. cxd5 exd5
8. e3 Bf5 9. Ne2 Nbd7 10. Ng3 Bg6 11. Bd3 c5 12. O-O Re8 13. Re1 Qc7 14.
Bxg6 hxg6 15. e4 cxd4 16. cxd4 Rac8 17. Bg5 Qc2 18. Bxf6 Qxd1 19. Rexd1
Nxf6 20. e5 Nh5 21. Ne2 Rc2 22. Kf1 g5 23. Rdc1 Rec8 24. g3 f6 25. Rxc2
Rxc2 26. Rb1 b6 27. Rb5 fxe5 28. dxe5 Rc5 29. Nd4 Kf7 30. Ke2 g6 31. Kd3
Ng7 32. Rb1 Ra5 33. Nc2 Ne6 34. Rb4 Rc5 35. h4 gxh4 36. Rxh4 d4 37. Nxd4
Rxe5 38. Nxe6 Kxe6 39. a4 Rg5 40. Re4+ Kf6 1/2-1/2
[Event "?"]
[Site "Wch"]
[Date "1961.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1-0"]
1. c4 Nf6 2. Nc3 e6 3. d4 Bb4 4. a3 Bxc3+ 5. bxc3 b6 6. f3 Ba6 7. e4 d5 8.
cxd5 Bxf1 9. Kxf1 exd5 10. Bg5 h6 11. Qa4+ c6 12. Bh4 dxe4 13. Re1 g5 14.
Bf2 Qe7 15. Ne2 b5 16. Qc2 Qxa3 17. h4 gxh4 18. Bxh4 Nbd7 19. Ng3 O-O-O 20.
Nxe4 Rhe8 21. Kf2 Nxe4+ 22. fxe4 f6 23. Ra1 Qe7 24. Rxa7 Qxe4 25. Qxe4 Rxe4
26. Ra8+ Nb8 27. Bg3 Kb7 28. Rha1 Rc8 29. R8a7+ Kb6 30. Bxb8 b4 31. Bd6
bxc3 32. Bc5+ Kb5 33. R1a4 1-0
[Event "?"]
[Site "Wch"]
[Date "1961.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1-0"]
1. c4 Nf6 2. Nc3 e6 3. d4 Bb4 4. e3 O-O 5. Bd3 d5 6. a3 dxc4 7. Bxc4 Bd6 8.
Nf3 Nc6 9. Nb5 e5 10. Nxd6 Qxd6 11. dxe5 Qxd1+ 12. Kxd1 Ng4 13. Ke2 Ncxe5
14. Bd5 c6 15. Be4 Be6 16. Nd2 Rad8 17. h3 Nf6 18. Bc2 Rd7 19. b3 Rfd8 20.
Rd1 Nd3 21. Bxd3 Rxd3 22. Bb2 R3d7 23. Bxf6 gxf6 24. b4 Bf5 25. Nb3 Bd3+
26. Ke1 b6 27. Rac1 Be4 28. f3 Rxd1+ 29. Rxd1 Rxd1+ 30. Kxd1 Bd5 31. Nd4 c5
32. bxc5 bxc5 33. Nb5 a6 34. Nc7 Bc4 35. Ne8 f5 36. h4 Kf8 37. Nd6 Bf1 38.
g3 Ke7 39. Nxf5+ Ke6 40. e4 Ke5 41. Kd2 1-0
[Event "?"]
[Site "Wch"]
[Date "1961.??.??"]
[Round "?"]
[White "Botvinnik, Mikhail"]
[Black "Tal, M."]
[Result "1-0"]
1. c4 Nf6 2. Nc3 e6 3. d4 Bb4 4. e3 O-O 5. Bd3 d5 6. a3 dxc4 7. Bxc4 Bd6 8.
Nf3 Nc6 9. b4 e5 10. Bb2 Bg4 11. d5 Ne7 12. h3 Bd7 13. Ng5 Ng6 14. Ne6 fxe6
15. dxe6 Kh8 16. exd7 Qxd7 17. O-O Qf5 18. Nd5 Ng8 19. Qg4 Qc2 20. Qe2 Qf5
21. Qg4 Qc2 22. Qe2 Qf5 23. e4 Qd7 24. Rad1 Rad8 25. Qg4 Qe8 26. g3 Nh6 27.
Qh5 Ng8 28. Qe2 N6e7 29. Ne3 Nh6 30. Ng4 Nxg4 31. hxg4 Nc6 32. Kg2 Be7 33.
Bd5 Nd4 34. Bxd4 exd4 35. Bc4 c5 36. b5 Bf6 37. f4 d3 38. Rxd3 Rxd3 39.
Bxd3 Bd4 40. e5 g6 41. Rh1 Kg7 42. Qe4 b6 43. Bc4 1-0
[Event "WM Moskau"]
[Site "?"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik"]
[Black "Tal, Mikhail N."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 Ne4 6. Nh3 c5 7. e3 Qa5
8. Bd2 cxd4 9. cxd4 Nxd2 10. Qxd2 Qxd2+ 11. Kxd2 b6 12. Bd3 Ba6 13. Rhc1
Nc6 14. Rab1 Ke7 15. c5 Bxd3 16. Kxd3 Rab8 17. Rb5 bxc5 18. Rcxc5 a6 19.
Rxb8 Rxb8 20. Kc2 Rc8 21. Nf4 d6 22. Rc3 g5 1/2-1/2
[Event "WM Moskau"]
[Site "?"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik"]
[Black "Tal, Mikhail N."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 Ne4 6. Qc2 f5 7. Nh3 O-O
8. f3 Nf6 9. c5 b6 10. cxb6 cxb6 11. e3 Qc7 12. Bd2 Ne8 13. c4 Ba6 14. Rc1
Nd6 15. Qa4 Qc6 16. Qxc6 Nxc6 17. Bb4 Nxb4 18. axb4 Bxc4 19. Bxc4 Rfc8 20.
Bxe6+ dxe6 21. Kd2 Kf7 22. Nf4 a5 23. bxa5 bxa5 24. Kd3 a4 25. Rxc8 Rxc8
26. Ra1 Nc4 27. Rb1 a3 28. Rb7+ Kf6 29. Ra7 g5 30. Nh5+ Kg6 31. g4 Nb2+ 32.
Kd2 Nc4+ 33. Kd3 Nb2+ 34. Kd2 Nc4+ 35. Ke2 Rc6 36. h3 e5 37. dxe5 fxg4 38.
hxg4 Nxe5 39. Rxa3 Rc2+ 40. Kf1 Kf7 41. e4 Rd2 42. Ke1 Rg2 43. Rb3 Ke7 44.
Ng7 Nxf3+ 45. Rxf3 Rxg4 46. Nf5+ Ke6 47. Ng3 h5 48. Nxh5 Rxe4+ 49. Kf2 Ke5
50. Kg3 Rh4 51. Ng7 Rf4 52. Ra3 Rd4 53. Ra6 Rd6 54. Ra7 Rd4 55. Rf7 Rf4 56.
Re7+ Kf6 57. Ra7 Re4 58. Nh5+ Kg6 59. Kf3 Rb4 60. Ng3 Rf4+ 61. Ke3 Rf7 62.
Ra5 Rf6 63. Ne4 Rf5 64. Ra6+ Kg7 65. Ng3 Re5+ 66. Kd4 Rb5 67. Ke4 Kf7 68.
Nf5 Rb4+ 69. Nd4 Rb1 70. Nf3 Rb4+ 71. Nd4 Rb1 72. Nc6 Kg6 73. Ne5+ Kh5 74.
Ra5 Re1+ 75. Kf3 Rf1+ 76. Kg3 Rf4 1/2-1/2
[Event "WM Moskau"]
[Site "?"]
[Date "1960.??.??"]
[Round "?"]
[White "Botvinnik"]
[Black "Tal, Mikhail N."]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 Ne4 6. Qc2 f5 7. Nh3 d6
8. f3 Nf6 9. e4 fxe4 10. fxe4 e5 11. Nf2 O-O 12. Be2 c5 13. dxe5 dxe5 14.
O-O Nc6 15. Bg5 Qe8 16. Nd1 Qg6 17. Bxf6 Rxf6 18. Ne3 Rxf1+ 19. Rxf1 Be6
20. Qd3 Rd8 21. Nd5 Rf8 22. Nc7 Rxf1+ 23. Bxf1 Qf7 24. Qd6 Bc8 25. Na6 Qf4
26. Qd5+ Kh8 27. Qxc5 Be6 28. Nc7 Bg8 29. Qf2 Qxe4 30. Ne8 Qg6 31. Qf8 e4
32. Nd6 Ne5 33. c5 Nd3 34. Nf5 Ne5 35. Ne7 Qf7 36. Qxf7 Bxf7 37. Kf2 Bc4
38. Bxc4 Nxc4 39. c6 bxc6 40. Nxc6 a5 41. a4 1/2-1/2
[Event "WM Moskau"]
[Site "?"]
[Date "1961.??.??"]
[Round "?"]
[White "Botvinnik"]
[Black "Tal, Mikhail N."]
[Result "1/2-1/2"]
1. c4 Nf6 2. Nc3 e6 3. d4 Bb4 4. e3 O-O 5. Bd3 d5 6. a3 dxc4 7. Bxc4 Bd6 8.
Nf3 Nc6 9. b4 e5 10. Bb2 Bg4 11. dxe5 Nxe5 12. Be2 Qe7 13. Nb5 Rfd8 14. Qc2
a6 15. Nxd6 cxd6 16. Qd1 Rac8 17. O-O Ne4 18. Nd4 Bxe2 19. Qxe2 Nc4 20.
Rac1 d5 21. Qg4 Qd7 22. Qxd7 Rxd7 23. Rc2 Ned6 24. Rd1 Rdd8 25. Nb3 Nxb2
26. Rxb2 Nc4 27. Ra2 b6 28. Kf1 f6 29. a4 Ne5 30. b5 Rc3 31. Nd4 Ra8 32.
Rda1 a5 33. Rd1 Rac8 34. Nf5 R8c7 35. Rxd5 Kf7 36. Rd1 Ke6 37. Nd4+ Kf7 38.
Ke2 R7c4 39. h3 Rb4 40. Nc2 Rbc4 41. Rd2 Ke7 42. Nd4 g6 43. Rd1 Nd7 44.
Nc6+ Ke8 45. Rd6 Rc2+ 46. Rxc2 Rxc2+ 47. Kf3 Ra2 48. Re6+ Kf8 49. Rd6 Ke8
50. Re6+ Kf8 51. Kg3 Rxa4 52. Re7 Nc5 53. Rxh7 Ne4+ 54. Kh2 Nd6 55. Rh8+
Kf7 56. Rb8 Nc4 57. Rc8 Nd2 58. g4 Ra2 59. Rb8 Ne4 60. Rxb6 Rxf2+ 61. Kg1
Rb2 62. Nxa5 Nd2 63. Nc6 Nc4 64. Rb7+ Ke6 65. h4 Kd5 66. Rd7+ Kc5 67. Rd3
Kxb5 68. Nd4+ Kc5 69. Nf3 Re2 70. h5 gxh5 71. gxh5 Nxe3 72. h6 Rg2+ 73. Kh1
Rg3 1/2-1/2

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,20 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
[Annotator "Barnes, David J."]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,18 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {Time control} 1/2-1/2

View File

@@ -0,0 +1,6 @@
b2b3 e7e5 c1b2 d7d6 d2d4 e5d4 d1d4 b8c6 d4d2 g8f6 b1c3 c8e6 e2e4 d6d5 e4d5
e6d5 d2e3+ f8e7 g1f3 e8g8 f1e2 f8e8 e1c1 e7b4 e3d3 b4c3 b2c3 d8e7 h1e1 f6e4
c3b2 a8d8 d3e3 b7b6 e2b5 e7e6 f3d4 c6d4 d1d4 c7c5 d4e4 d5e4 b5e8 d8e8 f2f3
e4d5 e3e6 e8e6 e1e6 d5e6 c1d2 g8f8 b2e5 b6b5 e5b8 a7a6 b8a7 c5c4 d2c3 f8e7
c3d4 e7d6 a7c5+ d6d7 c5a7 d7d6 a7c5+ d6d7 d4c3 g7g6 c5d4 f7f5 1/2-1/2

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,23 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "1-0"]
[SetUp "1"]
[FEN "1r5k/q4prp/p4NpQ/P1N1p3/8/3B1R2/1PP3PP/7K w - - 0 31"]
31. Rh3 -- 32. Qxh7+ Rxh7 33. Rxh7# 1-0
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "*"]
[SetUp "1"]
[FEN "4r1k1/2p2p2/5np1/Qp4q1/2p3P1/2B2P2/PP6/K6R w - - 0 1"]
1. Qxb5 -- (1... Qxb5 2. Bxf6 Re1+ 3. Rxe1 Qc6 4. g5)(1... Qe3 2. Qxe8+) *

View File

@@ -0,0 +1,29 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4 Qh4# 0-1
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,93 @@
[Event "?"]
[Site "Sarajevo"]
[Date "1972"]
[Round "?"]
[White "Petrosian,T"]
[Black "Hort"]
[Result "1-0"]
1. Nf3 c5 2. b3 d5 3. e3 Nf6 4. Bb2 e6 5. c4 Nc6 6. cxd5 exd5 7. Be2 Be7 8.
O-O O-O 9. d4 Bg4 10. dxc5 Bxc5 11. Nc3 Rc8 12. Rc1 Be7 13. Nd4 Bxe2 14.
Ncxe2 Qd7 15. Nf4 Rfd8 16. Qd3 Ne4 17. Nxc6 bxc6 18. Rc2 Bf8 19. Rfc1 Qb7
20. Qe2 Re8 21. Qg4 g6 22. Qd1 Bd6 23. Nxd5 Rcd8 24. Rxc6 Qb8 25. f4 Re6
26. Qd4 1-0
[Event "?"]
[Site "Buenos Aires m"]
[Date "1971"]
[Round "6"]
[White "Petrosian,T"]
[Black "Fischer,R"]
[Result "0-1"]
1. Nf3 c5 2. b3 d5 3. Bb2 f6 4. c4 d4 5. d3 e5 6. e3 Ne7 7. Be2 Nec6 8.
Nbd2 Be7 9. O-O O-O 10. e4 a6 11. Ne1 b5 12. Bg4 Bxg4 13. Qxg4 Qc8 14. Qe2
Nd7 15. Nc2 Rb8 16. Rfc1 Qe8 17. Ba3 Bd6 18. Ne1 g6 19. cxb5 axb5 20. Bb2
Nb6 21. Nef3 Ra8 22. a3 Na5 23. Qd1 Qf7 24. a4 bxa4 25. bxa4 c4 26. dxc4
Nbxc4 27. Nxc4 Nxc4 28. Qe2 Nxb2 29. Qxb2 Rfb8 30. Qa2 Bb4 31. Qxf7+ Kxf7
32. Rc7+ Ke6 33. g4 Bc3 34. Ra2 Rc8 35. Rxc8 Rxc8 36. a5 Ra8 37. a6 Ra7 38.
Kf1 g5 39. Ke2 Kd6 40. Kd3 Kc5 41. Ng1 Kb5 42. Ne2 Ba5 43. Rb2+ Kxa6 44.
Rb1 Rc7 45. Rb2 Be1 46. f3 Ka5 47. Rc2 Rb7 48. Ra2+ Kb5 49. Rb2+ Bb4 50.
Ra2 Rc7 51. Ra1 Rc8 52. Ra7 Ba5 53. Rd7 Bb6 54. Rd5+ Bc5 55. Nc1 Ka4 56.
Rd7 Bb4 57. Ne2 Kb3 58. Rb7 Ra8 59. Rxh7 Ra1 60. Nxd4+ exd4 61. Kxd4 Rd1+
62. Ke3 Bc5+ 63. Ke2 Rh1 64. h4 Kc4 65. h5 Rh2+ 66. Ke1 Kd3 0-1
[Event "Tilburg Grandmaster Tournament"]
[Site "Tilburg, NED"]
[Date "1982.09.??"]
[Round "2"]
[White "Karpov, Anatoly"]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nd2 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Ng5 e6 7. Qe2 Nb6
8. Bb3 a5 9. a3 a4 10. Ba2 h6 11. N5f3 c5 12. c3 Bd7 13. Ne5 cxd4 14. cxd4
Be7 15. Ngf3 O-O 16. O-O Be8 17. Bd2 Nbd5 18. Rfc1 Qb6 19. Bc4 Bc6 20. Re1
Nc7 21. Nxc6 bxc6 22. Bf4 Ncd5 23. Be5 Rfd8 24. Rad1 Bd6 25. Rd2 Bxe5 26.
dxe5 Nd7 27. g3 Nf8 28. Red1 Rd7 29. Qe4 Rb7 30. Rc2 Rab8 31. Rdd2 Ne7 32.
Kg2 Qa5 33. h4 Rd7 34. Be2 Rd5 35. Rd4 Rxd4 36. Qxd4 Nd5 37. Rxc6 Qa8 38.
Rc4 Qb7 39. Rc2 Nb6 40. Bb5 Ng6 41. Qd6 Qa8 42. Bc6 1-0
[Event "?"]
[Site "Moscow"]
[Date "1973.??.??"]
[Round "15"]
[White "Tal,M"]
[Black "Petrosian,T"]
[Result "0-1"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Ng5 e6 7. Qe2 Nb6
8. Bb3 a5 9. a4 h6 10. N5f3 c5 11. Bf4 Bd6 12. Be5 O-O 13. O-O-O c4 14.
Bxc4 Nxa4 15. Nh3 Nb6 16. g4 a4 17. g5 hxg5 18. Nhxg5 a3 19. b3 Bb4 20.
Rdg1 a2 21. Kb2 Nxc4+ 22. Qxc4 Nd5 23. Ne4 f6 24. Bf4 Ba3+ 25. Ka1 Nxf4 26.
h4 Rf7 27. Rg4 Qa5 0-1
[Event "?"]
[Site "Moscow"]
[Date "1973.??.??"]
[Round "2"]
[White "Petrosian,T"]
[Black "Kuzmin,G"]
[Result "1/2-1/2"]
1. c4 Nf6 2. d4 e6 3. Nc3 Bb4 4. e3 c5 5. Bd3 O-O 6. Nf3 d5 7. O-O dxc4 8.
Bxc4 a6 9. a3 Ba5 10. dxc5 Bxc3 11. bxc3 Qa5 12. a4 Nbd7 13. c6 bxc6 14.
Qc2 c5 15. e4 Qc7 16. Re1 Ng4 17. Kh1 Re8 18. h3 Ngf6 19. e5 Nd5 20. Ng5
Nf8 21. f4 Bb7 22. Ne4 Ng6 23. Qf2 Nb6 24. Bf1 Bxe4 25. Rxe4 Qc6 26. Qc2
Nd5 27. a5 Red8 28. Kh2 Rab8 29. Rea4 Nge7 30. Bd3 Nf5 31. Bxf5 exf5 32.
Qxf5 Nxc3 33. Rc4 1/2-1/2
[Event "?"]
[Site "Moscow"]
[Date "1973.??.??"]
[Round "10"]
[White "Petrosian,T"]
[Black "Smyslov,V"]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 c5 5. Bd3 b6 6. Ne2 Nc6 7. O-O cxd4 8.
exd4 Bb7 9. d5 Ne5 10. Bf4 Nxd3 11. Qxd3 exd5 12. cxd5 O-O 13. a3 Bxc3 14.
Nxc3 Re8 15. Bd6 Ng4 16. Qg3 Nh6 17. Rfe1 Nf5 18. Qf4 Qf6 19. Be5 Qg6 20.
Qa4 a6 21. Bf4 b5 22. Qb4 Rec8 23. Qe4 h5 24. Qd3 Rc4 25. Re4 Nh4 26. Bg3
Rxe4 27. Nxe4 Nxg2 28. Kxg2 h4 29. Rd1 hxg3 30. hxg3 Rc8 31. f3 f5 1/2-1/2

View File

@@ -0,0 +1,9 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4 Qh4# 0-1

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,9 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4 Qh4# 0-1

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,63 @@
[Event "Tilburg Wahls,M"]
[Site "Tilburg NED"]
[Date "1991.10.25"]
[Round "7"]
[White "Anatoly Karpov"]
[Black "Garry Kasparov"]
[Result "1/2-1/2"]
1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 8.
d5 Ne7 9. Nd2 a5 10. Rb1 Nd7 11. a3 f5 12. b4 Kh8 13. f3 Ng8 14. Qc2 Ngf6
15. Nb5 axb4 16. axb4 Nh5 17. g3 Ndf6 18. c5 Bd7 19. Rb3 Nxg3 20. hxg3 Nh5
21. f4 exf4 22. c6 bxc6 23. dxc6 Nxg3 24. Rxg3 fxg3 25. cxd7 g2 26. Rf3
Qxd7 27. Bb2 fxe4 28. Rxf8+ Rxf8 29. Bxg7+ Qxg7 30. Qxe4 Qf6 31. Nf3 Qf4
32. Qe7 Rf7 33. Qe6 Rf6 34. Qe8+ Rf8 35. Qe7 Rf7 36. Qe6 Rf6 37. Qb3 g5 38.
Nxc7 g4 39. Nd5 Qc1+ 40. Qd1 Qxd1+ 41. Bxd1 Rf5 42. Ne3 Rf4 43. Ne1 Rxb4
44. Bxg4 h5 45. Bf3 d5 46. N3xg2 h4 47. Nd3 Ra4 48. Ngf4 Kg7 49. Kg2 Kf6
50. Bxd5 Ra5 51. Bc6 Ra6 52. Bb7 Ra3 53. Be4 Ra4 54. Bd5 Ra5 55. Bc6 Ra6
56. Bf3 Kg5 57. Bb7 Ra1 58. Bc8 Ra4 59. Kf3 Rc4 60. Bd7 Kf6 61. Kg4 Rd4 62.
Bc6 Rd8 63. Kxh4 Rg8 64. Be4 Rg1 65. Nh5+ Ke6 66. Ng3 Kf6 67. Kg4 Ra1 68.
Bd5 Ra5 69. Bf3 Ra1 70. Kf4 Ke6 71. Nc5+ Kd6 72. Nge4+ Ke7 73. Ke5 Rf1 74.
Bg4 Rg1 75. Be6 Re1 76. Bc8 Rc1 77. Kd4 Rd1+ 78. Nd3 Kf7 79. Ke3 Ra1 80.
Kf4 Ke7 81. Nb4 Rc1 82. Nd5+ Kf7 83. Bd7 Rf1+ 84. Ke5 Ra1 85. Ng5+ Kg6 86.
Nf3 Kg7 87. Bg4 Kg6 88. Nf4+ Kg7 89. Nd4 Re1+ 90. Kf5 Rc1 91. Be2 Re1 92.
Bh5 Ra1 93. Nfe6+ Kh6 94. Be8 Ra8 95. Bc6 Ra1 96. Kf6 Kh7 97. Ng5+ Kh8 98.
Nde6 Ra6 99. Be8 Ra8 100. Bh5 Ra1 101. Bg6 Rf1+ 102. Ke7 Ra1 103. Nf7+ Kg8
104. Nh6+ Kh8 105. Nf5 Ra7+ 106. Kf6 Ra1 107. Ne3 Re1 108. Nd5 Rg1 109. Bf5
Rf1 110. Ndf4 Ra1 111. Ng6+ Kg8 112. Ne7+ Kh8 113. Ng5 Ra6+ 114. Kf7 Rf6+
1/2-1/2
[Event "ch-ARM"]
[Site "Yerevan ARM"]
[Date "2001.09.13"]
[Round "1"]
[White "Smbat Gariginovich Lputian"]
[Black "Gevorg Harutjunyan"]
[Result "1-0"]
1. d4 g6 2. c4 Bg7 3. Nc3 Nf6 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 8.
d5 Ne7 9. b4 a5 10. bxa5 Rxa5 11. a4 b6 12. Nd2 Ra8 13. Nb3 Nd7 14. a5 Ba6
15. axb6 cxb6 16. Bd2 Qb8 17. Ra4 f5 18. Qa1 Bb7 19. Rxa8 Bxa8 20. Qa3 Nc8
21. f3 Bb7 22. Rb1 Rf7 23. Nc1 Nc5 24. Nd3 Qc7 25. Nxc5 dxc5 26. Qb2 Bf6
27. Nb5 Qe7 28. Bc3 fxe4 29. fxe4 h5 30. Rd1 Bg7 31. d6 Qf6 32. Bf3 Rd7 33.
Rf1 Qg5 34. h4 Qe3+ 35. Kh2 Qd3 36. Re1 Qxc4 37. Rd1 Qf7 38. Bxe5 Bc6 39.
Bxg7 Qxg7 40. e5 Bxb5 41. Qb3+ Kh7 42. Re1 Na7 43. Kh1 Qf8 44. Qd5 Qd8 45.
Qe4 Rg7 46. Qf4 Nc8 47. Bd5 Bd3 48. Be6 Na7 49. Rd1 Be2 50. Rd2 Bb5 51. Qf6
Nc6 52. d7 Re7 53. Rd6 c4 54. Bf5 Nxe5 55. Bxg6+ Kg8 56. Bf5 Nf7 57. Qg6+
Kf8 58. Rf6 Rxd7 59. Bxd7 Qxd7 60. Rxb6 Qe8 61. Qxh5 Qe1+ 62. Kh2 Be8 63.
Qc5+ Kg7 64. Qxc4 Qe5+ 65. g3 Qf5 66. Qd4+ Kh7 67. Rf6 Qc2+ 68. Rf2 Qg6 69.
g4 Nh6 70. Kg3 Bf7 71. Rf6 Qb1 72. Qe3 Qb8+ 73. Kh3 Bg6 74. Qe7+ Bf7 75.
Rxf7+ Nxf7 76. Qxf7+ Kh8 77. Qf3 Qb1 78. h5 Qe1 79. g5 Qe6+ 80. Kg2 Kg7 81.
Qb7+ Kh8 82. Qb8+ Kg7 83. Qc7+ Kh8 84. Qd8+ Kg7 85. Qd4+ Kg8 86. h6 Qe2+
87. Kg3 Qe1+ 88. Kg4 Qe2+ 89. Kg3 Qe1+ 90. Qf2 Qe5+ 91. Qf4 Qe1+ 92. Kg2
Qe2+ 93. Kh3 Qe6+ 94. Kh4 Qe1+ 95. Kh5 Qe2+ 96. Kh4 Qe1+ 97. Kg4 Qe6+ 98.
Qf5 Qe2+ 99. Qf3 Qe6+ 100. Kh4 Qe1+ 101. Kh3 Qe6+ 102. Kg2 Qe5 103. Qb3+
Kh8 104. Qg3 Qe2+ 105. Kg1 Qd1+ 106. Kf2 Qd2+ 107. Kf3 Qd3+ 108. Kf4 Qd6+
109. Kg4 Qe6+ 110. Kh5 Qe2+ 111. Kh4 Qe4+ 112. Kh3 Qh1+ 113. Kg4 Qe4+ 114.
Qf4 Qe6+ 115. Kh4 Qe1+ 116. Kh5 Qe2+ 117. Kg6 Qe8+ 118. Qf7 Qe4+ 119. Qf5
Qe8+ 120. Kf6 Qf7+ 121. Ke5 Qe7+ 122. Kf4 Qb4+ 123. Qe4 Qd2+ 124. Kg4 Qd7+
125. Kh4 Qf7 126. Qd4+ Kh7 127. Qd3+ Kh8 128. Qc3+ Kh7 129. Qd4 Kg8 130.
Qd3 Kh8 131. Kg3 Qc7+ 132. Kg4 Qc8+ 133. Kh4 Qb7 134. Qc3+ Kh7 135. Qd3+
Kh8 136. Qd4+ Kh7 137. Kg3 Qb3+ 138. Kh4 Qf7 139. Qe4+ Kh8 140. Kg3 Qc7+
141. Qf4 Qf7 142. Qf6+ 1-0

View File

@@ -0,0 +1,81 @@
[Event "65th ch-ARG w 2013"]
[Site "Villa Martelli ARG"]
[Date "2013.04.07"]
[Round "3.1"]
[White "Acosta,Florencia"]
[Black "Fernandez,Maria"]
[Result "1-0"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. f3 g6 6. c4 Bg7 7. Nc3 O-O 8.
Be2 Nc6 9. Nc2 Be6 10. Be3 Rc8 11. O-O Na5 12. b3 a6 13. Qd2 b5 14. e5 Nd7
15. cxb5 Bxe5 16. Bd4 axb5 17. Bxb5 Nc6 18. Rad1 Nxd4 19. Nxd4 Nf6 20. f4
Bxd4+ 21. Qxd4 Rxc3 22. Qxc3 Qb6+ 23. Kh1 Qxb5 24. Rfe1 Rc8 25. Qb2 Qf5 26.
Rd4 Rc2 27. Qb1 Ng4 28. a4 Nxh2 29. Rde4 Nf3 30. Qxc2 Qh5# 1-0
[Event "TCh-NED Meesterklasse 2012-13"]
[Site "Netherland NED"]
[Date "2013.04.06"]
[Round "8.5"]
[White "Geurink,J"]
[Black "Bosch,Je"]
[Result "0-1"]
1. e4 e5 2. Nf3 Nc6 3. Bc4 Be7 4. d3 Nf6 5. O-O d6 6. a4 O-O 7. Re1 Kh8 8.
d4 exd4 9. Nxd4 Nxd4 10. Qxd4 Ng4 11. Be2 Ne5 12. Nc3 f5 13. exf5 Bxf5 14.
Nd5 Bf6 15. Nxf6 Qxf6 16. Be3 Bxc2 17. f4 Nc6 18. Qxf6 gxf6 19. Bf3 Rae8
20. Bf2 Kg7 21. Bh5 Rxe1+ 22. Rxe1 Bxa4 23. Re3 Bc2 24. Rg3+ Kh8 25. Bf3 a6
26. Bd5 Bf5 27. Rc3 Bd7 28. Bh4 h5 29. Rg3 Kh7 30. Rb3 Nd8 31. Re3 Bc6 32.
Re7+ Kg6 33. Bb3 f5 34. Rxc7 Re8 35. Bxd8 Rxd8 36. Bf7+ Kh6 37. Be6 Be4 38.
Kf2 Re8 39. Bf7 Rf8 40. g3 a5 41. Ke3 Ra8 42. Bc4 b5 43. Bxb5 Rb8 44. Bc6
Rb3+ 45. Kd4 Rd3+ 46. Kc4 d5+ 47. Kb5 Rb3+ 48. Kxa5 Rxb2 49. Rd7 Rxh2 50.
Bxd5 Bxd5 51. Rxd5 Kg6 52. Rd6+ Kf7 53. Kb4 h4 54. gxh4 Rxh4 55. Kc3 Rxf4
56. Kd3 Re4 57. Ra6 Re8 58. Rb6 Kg7 59. Ra6 Re4 60. Rb6 Kf7 61. Ra6 Re6 62.
Rxe6 Kxe6 63. Ke3 Ke5 64. Kf3 f4 65. Kf2 Ke4 66. Ke2 f3+ 67. Kf2 Kf4 68.
Kf1 Kg3 69. Kg1 f2+ 70. Kf1 Kf3 0-1
[Event "48th Capablanca Open II 2013"]
[Site "Havana CUB"]
[Date "2013.04.28"]
[Round "7.53"]
[White "Rodriguez Caballero,M"]
[Black "Torres Larco,Denisse"]
[Result "1/2-1/2"]
1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nf6 5. Nc3 Bb4 6. Nxc6 bxc6 7. Bd3
d5 8. exd5 cxd5 9. O-O O-O 10. Bg5 c6 11. Qf3 Be7 12. Rfe1 Be6 13. h3 Rb8
14. Rab1 h6 15. Bf4 Bd6 16. Ne2 c5 17. c3 Qc7 18. Bxh6 gxh6 19. Qxf6 Rb6
20. Qxh6 Bf5 21. Qg5+ Bg6 22. Bxg6 Bh2+ 23. Kh1 Rxg6 24. Qxd5 Rd8 25. Qf3
Be5 26. Rbd1 Rb8 27. Nc1 c4 28. Rd5 Bf4 29. Ne2 Bh6 30. Ng3 Rxb2 31. Re8+
Kh7 32. Rdd8 Bg7 33. Qh5+ Rh6 34. Qf5+ Rg6 35. Rd7 Qc6 36. Ne4 Rxf2 37.
Ng5+ Kh6 38. Nxf7+ Kh7 39. Qh5+ Rh6 40. Ng5# 1/2-1/2
[Event "41st TCh-GRE"]
[Site "Rio (Achaia) GRE"]
[Date "2013.07.02"]
[Round "1.8"]
[White "Papakonstantinou,Di1"]
[Black "Palaskos,M"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. e5 Nfd7 7. d4 Qb6
8. e6 fxe6 9. Qg4 g6 10. Bd3 Bg7 11. Ne2 e5 12. c3 O-O 13. h4 c5 14. h5 e4
15. Bc2 e5 16. Bb3 c4 17. Ba4 Nf6 18. Qh4 Nbd7 19. hxg6 hxg6 20. Qg5 Qe6
21. Qxg6 Qf7 22. Qg3 exd4 23. cxd4 a6 24. Bh6 b5 25. Bc2 Rac8 26. Nf4 Rc6
27. Rh4 Re8 28. Ke2 Nf8 29. Rah1 Re7 30. Bg5 N8h7 31. Bxf6 Rxf6 32. Rxh7
Rxf4 33. Rh8# 0-1
[Event "100th ch-GBR 2013"]
[Site "Torquay ENG"]
[Date "2013.08.01"]
[Round "4.38"]
[White "Hegarty,S"]
[Black "Armstrong,M"]
[Result "1/2-1/2"]
1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. Bd3 a6
8. f4 c5 9. Nf3 Nc6 10. dxc5 Nxc5 11. O-O Nxd3 12. cxd3 Bd7 13. d4 O-O 14.
Rc1 Rac8 15. Qd3 f6 16. Rce1 f5 17. Kh1 Nd8 18. Rg1 Nf7 19. g4 fxg4 20.
Rxg4 Nh6 21. Ng5 Nf5 22. Reg1 Qb4 23. Nxh7 Qxb2 24. Nd1 Qb5 25. Qh3 Kf7 26.
Nxf8 Rxf8 27. Ne3 Qd3 28. Qh5+ Kg8 29. Ng2 Qxd4 30. h3 Rc8 31. Qg5 Qd3 32.
Kh2 d4 33. Nh4 Rc2+ 34. R4g2 Rc3 35. Qg4 Bc6 36. Nxf5 Bxg2 37. Qxg7#
1/2-1/2

View File

@@ -0,0 +1,4 @@
e4 e5 Nf3 Nc6 Bb5 *
Nf3 Nc6 e4 e5 { Match game 1 at 4 ply. } Bc4 *
e4 e5 Nf3 { Match game 1 at 3 and 4 ply. } Nc6 d4 *
e4 e5 Bb5 Nc6 Nf3 { Match game 1 at 5 ply. } *

View File

@@ -0,0 +1,597 @@
[Event "Milwaukee Northwestern"]
[Site "?"]
[Date "1957"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Kampars, N."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 e6 6. d4 Nd7 7. Bd3 dxe4
8. Nxe4 Ngf6 9. O-O Nxe4 10. Qxe4 Nf6 11. Qe3 Nd5 12. Qf3 Qf6 13. Qxf6 Nxf6
14. Rd1 O-O-O 15. Be3 Nd5 16. Bg5 Be7 17. Bxe7 Nxe7 18. Be4 Nd5 19. g3 Nf6
20. Bf3 Kc7 21. Kf1 Rhe8 22. Be2 e5 23. dxe5 Rxe5 24. Bc4 Rxd1+ 25. Rxd1
Re7 26. Bb3 Ne4 27. Rd4 Nd6 28. c3 f6 29. Bc2 h6 30. Bd3 Nf7 31. f4 Rd7 32.
Rxd7+ Kxd7 33. Kf2 Nd6 34. Kf3 f5 35. Ke3 c5 36. Be2 Ke6 37. Bd3 1/2-1/2
[Event "US Open"]
[Site "?"]
[Date "1957"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Addison, William G."]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. Bc4 Bd6 7. Qe2+
Qe7 8. Qxe7+ Kxe7 9. d4 Bf5 10. Bb3 Re8 11. Be3 Kf8 12. O-O-O Nd7 13. c4
Rad8 14. Bc2 Bxc2 15. Kxc2 f5 16. Rhe1 f4 17. Bd2 Nf6 18. Ne5 g5 19. f3 Nh5
20. Ng4 Kg7 21. Bc3 Kg6 22. Rxe8 Rxe8 23. c5 Bb8 24. d5 cxd5 25. Rxd5 f5
26. Ne5+ Bxe5 27. Rxe5 Nf6 28. Rxe8 Nxe8 29. Be5 Kh5 30. Kd3 g4 31. b4 a6
32. a4 gxf3 33. gxf3 Kh4 34. b5 axb5 35. a5 Kh3 36. c6 1-0
[Event "West Orange Open"]
[Site "?"]
[Date "1957"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Goldsmith, Julius"]
[Result "1-0"]
1. e4 c6 2. Nc3 d6 3. d4 Nd7 4. Nf3 e5 5. Bc4 Be7 6. dxe5 Nxe5 7. Nxe5 dxe5
8. Qh5 g6 9. Qxe5 Nf6 10. Bg5 Bd7 11. O-O-O O-O 12. Rxd7 Qxd7 13. Bxf6 Bxf6
14. Qxf6 Rae8 15. f3 Qc7 16. h4 Qe5 17. Qxe5 Rxe5 18. Rd1 Re7 19. Rd6 Kg7
20. a3 f5 21. Kd2 fxe4 22. Nxe4 Rf4 23. h5 gxh5 24. Rd8 h4 25. Rg8+ Kh6 26.
Ke3 Rf5 27. Rg4 Rh5 28. Kf2 Rg7 29. Rxg7 Kxg7 30. Bf1 Rd5 31. Bd3 h6 32.
Ke3 Rh5 33. Nd6 h3 34. gxh3 Rxh3 35. Nxb7 Rh5 36. b4 Re5+ 37. Kf4 Re7 38.
Nd8 c5 39. bxc5 Kf6 40. c6 Rc7 41. Be4 Ke7 42. Nb7 Kf6 43. Nd6 Re7 44. c7
1-0
[Event "Bad Portoroz Interzonal"]
[Site "?"]
[Date "1958"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Cardoso, Rudolfo T."]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Bg4 5. h3 Bxf3 6. Qxf3 Nd7 7. Ng5
Ngf6 8. Qb3 e6 9. Qxb7 Nd5 10. Ne4 Nb4 11. Kd1 f5 12. c3 Rb8 13. Qxa7 fxe4
14. cxb4 Bxb4 15. Qd4 O-O 16. Bc4 Nc5 17. Qxd8 Rbxd8 18. Rf1 Rd4 19. b3
Bxd2 20. Ke2 Bxc1 21. Raxc1 Rfd8 22. Rfd1 Kf8 23. Rxd4 Rxd4 24. Rd1 Rxd1
25. Kxd1 Ke7 26. Kd2 Kd6 27. Kc3 Nd7 28. Kd4 Nf6 29. a4 c5+ 30. Ke3 g5 31.
Be2 Kc6 32. Bc4 e5 33. a5 h6 34. Kd2 h5 35. Ke3 h4 36. Be2 Kb7 37. Bc4 Kc6
38. Ke2 Kb7 39. Kd2 Kc6 40. Ke3 Kb7 41. Kd2 Kc7 42. g4 Kc6 43. Kc3 Ne8 44.
b4 Nd6 45. Bf1 cxb4+ 46. Kxb4 Nc8 47. Bg2 Kd5 48. a6 Na7 49. Ka5 Kc5 50.
Bxe4 Nb5 51. Bg2 Na7 52. Ka4 Nb5 53. Kb3 Kb6 54. Kc4 Kxa6 55. Kd5 Kb6 56.
Kxe5 Kc7 57. Kf6 Nc3 58. Kxg5 Nd1 59. f4 Kd6 60. Kxh4 Ke6 61. Kg5 Kf7 62.
f5 1-0
[Event "USA Championship"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Weinstein, Raymond"]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Be7 8.
Bg2 dxe4 9. dxe4 e5 10. O-O Nbd7 11. Nd1 O-O 12. Ne3 g6 13. Rd1 Qc7 14. Ng4
h5 15. Nxf6+ Nxf6 16. Bg5 Nh7 17. Bh6 Rfd8 18. Bf1 Bg5 19. Bxg5 Nxg5 20.
Qe3 Qe7 21. h4 Ne6 22. Bc4 b5 23. Bxe6 Qxe6 24. Qc5 Qc4 25. Qxc4 bxc4 26.
b3 Rd4 27. Rxd4 exd4 28. Kf1 Re8 29. f3 Re5 30. Rd1 c5 31. c3 dxc3 32. Rc1
f5 33. exf5 Rxf5 34. Rxc3 cxb3 35. Rxb3 c4 36. Ra3 Rc5 37. Ke2 c3 38. Kd1
c2+ 39. Kc1 a5 40. Rb3 Kg7 41. Rb7+ Kf6 42. Rb6+ Kg7 43. g4 1/2-1/2
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Benko, Pal"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 a5 11. a3 Bxd2+ 12. Nxd2 Qc5 13. Qd1 h5 14. h4
Nbd7 15. Bg2 Ng4 16. O-O g5 17. b4 Qe7 18. Nf3 gxh4 19. Nxh4 Nde5 20. Qd2
Rg8 21. Qf4 f6 22. bxa5 Rxa5 23. Rfb1 b5 24. Nf3 Ra4 25. Bh3 Nxf3+ 26. Qxf3
Kd7 27. Kg2 Qg7 28. Rb4 Rga8 29. Rxa4 Rxa4 30. Bxg4 hxg4 31. Qf4 Ra8 32.
Rh1 Rg8 33. a4 bxa4 34. Rb1 e5 35. Rb7+ Kd6 36. Rxg7 exf4 37. Rxg8 f3+ 38.
Kh1 Kc5 39. Rb8 1-0
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 Nbd7 11. Bg2 a5 12. a3 Bxd2+ 13. Nxd2 Qc5 14. Qd1
h5 15. Nf3 Qc3+ 16. Ke2 Qc5 17. Qd2 Ne5 18. b4 Nxf3 19. Bxf3 Qe5 20. Qf4
Nd7 21. Qxe5 Nxe5 22. bxa5 Kd7 23. Rhb1 Kc7 24. Rb4 Rxa5 25. Bg2 g5 26. f4
gxf4 27. gxf4 Ng6 28. Kf3 Rg8 29. Bf1 e5 30. fxe5 Nxe5+ 31. Ke2 c5 32. Rb3
b6 33. Rab1 Rg6 34. h4 Ra6 35. Bh3 Rg3 36. Bf1 Rg4 37. Bh3 Rxh4 38. Rh1 Ra8
39. Rbb1 Rg8 40. Rbf1 Rg3 41. Bf5 Rg2+ 42. Kd1 Rhh2 43. Rxh2 Rxh2 44. Rg1
c4 45. dxc4 Nxc4 46. Rg7 Kd6 47. Rxf7 Ne3+ 48. Kc1 Rxc2+ 49. Kb1 Rh2 50.
Rd7+ Ke5 51. Re7+ Kf4 52. Rd7 Nd1 53. Kc1 Nc3 54. Bh7 h4 55. Rf7+ Ke3 0-1
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 a5 11. a3 Be7 12. Bg2 a4 13. b4 Nbd7 14. O-O c5
15. Ra2 O-O 16. bxc5 Bxc5 17. Qe2 e5 18. f4 Rfc8 19. h4 Rc6 20. Bh3 Qc7 21.
fxe5 Nxe5 22. Bf4 Bd6 23. h5 Ra5 24. h6 Ng6 25. Qf3 Rh5 26. Bg4 Nxf4 27.
Bxh5 N4xh5 28. g4 Bh2+ 29. Kg2 Nxg4 30. Nd2 Ne3+ 0-1
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Olafsson, Fridrik"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 Nf6 4. e5 Ne4 5. Ne2 Qb6 6. d4 c5 7. dxc5 Qxc5 8.
Ned4 Nc6 9. Bb5 a6 10. Bxc6+ bxc6 11. O-O Qb6 12. e6 fxe6 13. Bf4 g6 14.
Be5 Nf6 15. Ng5 Bh6 16. Ndxe6 Bxg5 17. Nxg5 O-O 18. Qd2 Bf5 19. Rae1 Rad8
20. Bc3 Rd7 21. Ne6 Bxe6 22. Rxe6 d4 23. Bb4 Nd5 24. Ba3 Rf7 25. g3 Nc7 26.
Re5 Nd5 27. Qd3 Nf6 28. Qc4 Ng4 29. Re6 Qb5 30. Qxb5 axb5 31. Rxc6 Ne5 32.
Rc8+ Kg7 33. Bb4 Nf3+ 34. Kg2 e5 35. Rd1 g5 36. Bf8+ Rxf8 37. Rxf8 Kxf8 38.
Kxf3 Kf7 39. c3 Ke6 40. cxd4 exd4 41. Ke4 Rf7 42. f3 1-0
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Bxd2+ 10. Nxd2 e5 11. Bg2 c5 12. O-O Nc6 13. Qe2 g5 14. Nf3
h6 15. h4 Rg8 16. a3 Qe7 17. hxg5 hxg5 18. Qd2 Nd7 19. c3 O-O-O 20. cxd4
exd4 21. b4 Kb8 22. Rfc1 Nce5 23. Nxe5 Qxe5 24. Rc4 Rc8 25. Rac1 g4 26. Qb2
Rgd8 27. a4 Qe7 28. Rb1 Ne5 29. Rxc5 Rxc5 30. bxc5 Nxd3 31. Qd2 Nxc5 32.
Qf4+ Qc7 33. Qxg4 Nxa4 34. e5 Nc5 35. Qf3 d3 36. Qe3 d2 37. Bf3 Na4 38. Qe4
Nc5 39. Qe2 a6 40. Kg2 Ka7 41. Qe3 Rd3 42. Qf4 Qd7 43. Qc4 b6 44. Rd1 a5
45. Qf4 Rd4 46. Qh6 b5 47. Qe3 Kb6 48. Qh6+ Ne6 49. Qe3 Ka6 50. Be2 a4 51.
Qc3 Kb6 52. Qe3 Nc5 53. Bf3 b4 54. Qh6+ Ne6 55. Qh8 Qd8 56. Qh7 Qd7 57. Qh8
b3 58. Qb8+ Ka5 59. Qa8+ Kb5 60. Qb8+ Kc4 61. Qg8 Kc3 62. Bh5 Nd8 63. Bf3
a3 64. Qf8 Kb2 65. Qh8 Ne6 66. Qa8 a2 67. Qa5 Qa4 68. Rxd2+ Ka3 0-1
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Bxd2+ 10. Nxd2 e5 11. Bg2 c5 12. O-O Nc6 13. Qe2 Qe7 14. f4
O-O-O 15. a3 Ne8 16. b4 cxb4 17. Nc4 f6 18. fxe5 fxe5 19. axb4 Nc7 20. Na5
Nb5 21. Nxc6 bxc6 22. Rf2 g6 23. h4 Kb7 24. h5 Qxb4 25. Rf7+ Kb6 26. Qf2 a5
27. c4 Nc3 28. Rf1 a4 29. Qf6 Qc5 30. Rxh7 Rdf8 31. Qxg6 Rxf1+ 32. Bxf1
Rxh7 33. Qxh7 a3 34. h6 a2 35. Qg8 a1=Q 36. h7 Qd6 37. h8=Q Qa7 38. g4 Kc5
39. Qf8 Qae7 40. Qa8 Kb4 41. Qh2 Kb3 42. Qa1 Qa3 43. Qxa3+ Kxa3 44. Qh6 Qf7
45. Kg2 Kb3 46. Qd2 Qh7 47. Kg3 Qxe4 48. Qf2 Qh1 1/2-1/2
[Event "Yugoslavia Candidate Trn"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Smyslov, Vasily V."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bh5 5. exd5 cxd5 6. Bb5+ Nc6 7. g4 Bg6
8. Ne5 Rc8 9. h4 f6 10. Nxg6 hxg6 11. d4 e6 12. Qd3 Kf7 13. h5 gxh5 14.
gxh5 Nge7 15. Be3 Nf5 16. Bxc6 Rxc6 17. Ne2 Qa5+ 18. c3 Qa6 19. Qc2 Bd6 20.
Bf4 Bxf4 21. Nxf4 Rh6 22. Qe2 Qxe2+ 23. Kxe2 Rh8 24. Kd3 b5 25. Rhe1 b4 26.
cxb4 Rc4 27. Nxe6 Rxh5 28. b3 Rh3+ 29. Kd2 Rcc3 30. Nf4 Rhf3 31. Re2 g5 32.
Nxd5 Rcd3+ 33. Kc1 Rxd4 34. Ne3 Nxe3 35. fxe3 Rxb4 36. Kd2 g4 37. Rc1 Rb7
38. Rg1 Rd7+ 39. Kc2 f5 40. e4 Kf6 41. exf5 g3 42. Re8 Rg7 43. Rf8+ Ke7 44.
Ra8 Kd6 45. Rf8 Rf2+ 46. Kd3 g2 47. f6 Rg3+ 48. Kc4 Ke6 49. Re1+ Kf5 50. f7
Rg7 51. Rg1 Kf6 52. a4 Rxf7 1/2-1/2
[Event "Zurich"]
[Site "?"]
[Date "1959"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Larsen, Bent"]
[Result "1/2-1/2"]
1. e4 c6 2. Nf3 d5 3. Nc3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. a3 Bc5 8.
Be2 O-O 9. O-O Nbd7 10. Qg3 Bd4 11. Bh6 Ne8 12. Bg5 Ndf6 13. Bf3 Qd6 14.
Bf4 Qc5 15. Rab1 dxe4 16. dxe4 e5 17. Bg5 Bxc3 18. bxc3 b5 19. c4 a6 20.
Bd2 Qe7 21. Bb4 Nd6 22. Rfd1 Rfd8 23. cxb5 cxb5 24. Rd3 Qe6 25. Rbd1 Nb7
26. Bc3 Rxd3 27. cxd3 Re8 28. Kh2 h6 29. d4 Nd6 30. Re1 Nc4 31. dxe5 Nxe5
32. Bd1 Ng6 33. e5 Nd5 34. Bb3 Qc6 35. Bb2 Ndf4 36. Rd1 a5 37. Rd6 Qe4 38.
Rd7 Ne6 39. Bd5 Qe2 40. Bc3 b4 41. axb4 axb4 42. Bxb4 Qxe5 43. Ba5 Qxg3+
44. Kxg3 Re7 45. Rd6 Nef4 46. Bf3 Ne6 47. Bb6 Ne5 48. Bd5 Rd7 49. Rxd7 Nxd7
50. Be3 Nf6 51. Bc6 g5 52. Kf3 Kg7 53. Ba4 Nd5 54. Bc1 h5 55. Bb2+ Kh6 56.
Bb3 Ndf4 57. Bc2 Ng6 58. Kg3 Nef4 59. Be4 Nh4 60. Bf6 Nhg6 61. Kf3 Nh4+ 62.
Kg3 Nhg6 63. Kh2 h4 64. Kg1 Nh5 65. Bc3 Ngf4 66. Kf1 Ng7 67. Bf6 Nfh5 68.
Be5 f6 69. Bd6 f5 70. Bf3 Nf4 71. Ke1 Kg6 72. Kd2 Nge6 73. Be5 Nc5 74. Ke3
Nce6 75. Bc6 Kf7 76. Kf3 Ke7 77. Bb7 Ng6 78. Bc3 Ngf4 79. Ba6 Nd5 80. Be5
Nf6 81. Bd3 g4+ 82. Ke2 Nd7 83. Bh2 gxh3 84. gxh3 Kf6 85. Ke3 Ne5 86. Be2
Ng6 87. Bf1 f4+ 88. Kf3 Ne5+ 89. Ke4 Ng5+ 90. Kxf4 Nef3 91. Bg3 hxg3 92.
fxg3 1/2-1/2
[Event "Buenos Aires"]
[Site "?"]
[Date "1960"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Foguelman, Alberto"]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nh3 Nf6 7. Nf4 e5
8. dxe5 Qxd1+ 9. Kxd1 Ng4 10. Nxg6 hxg6 11. Ne4 Nxe5 12. Be2 f6 13. c3 Nbd7
14. Be3 O-O-O 15. Kc2 Nb6 16. h4 Nec4 17. Bf4 Nd5 18. Bg3 Nd6 19. Nxd6+
Bxd6 20. Bxd6 Rxd6 21. g3 Kc7 22. c4 Nb4+ 23. Kc3 c5 24. a3 Re8 25. Bf1 Nc6
26. Bd3 Ne5 27. Be4 Ng4 28. Bxg6 Re2 29. Rae1 Rxf2 30. Re7+ Kb6 31. Be4 Re2
32. Rxb7+ Ka6 33. Re7 Kb6 34. b4 Nf2 35. Rb7+ Ka6 36. b5+ Ka5 37. Rxa7+ Kb6
38. Ra6+ Kc7 39. b6+ Rxb6 40. Rxb6 Nxe4+ 41. Kd3 Kxb6 42. Rg1 Rd2+ 43. Kxe4
Rd4+ 44. Kf5 Rxc4 45. Re1 Rc3 46. g4 Rf3+ 47. Kg6 Rxa3 48. Kxg7 Rg3 49. Re4
f5 50. Re6+ Kb5 51. g5 Rg4 52. g6 Rxh4 53. Kf7 c4 54. g7 Rh7 55. Rg6 c3 56.
Kf6 Rxg7 57. Rxg7 Kc4 58. Kxf5 c2 1/2-1/2
[Event "Buenos Aires"]
[Site "?"]
[Date "1960"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Ivkov, Boris"]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 6. Nf3 Be7 7. c5 O-O 8.
b4 b6 9. Bd3 bxc5 10. bxc5 Nc6 11. O-O Bd7 12. h3 Ne8 13. Bf4 Bf6 14. Bb5
Nc7 15. Be2 Nxd4 16. Nxd4 e5 17. c6 Be8 18. Bg3 exd4 19. Bxc7 Qxc7 20. Nxd5
Qd6 21. Nxf6+ Qxf6 22. c7 Rc8 23. Rc1 Bc6 24. Rc4 Rxc7 25. Bd3 Rd7 26. Qc2
Bd5 27. Ra4 g6 28. Qc5 Rfd8 29. Bb5 Rd6 30. Rd1 Be6 31. Bd3 Rd5 32. Qxa7
Bxh3 33. Be4 R5d7 34. Qa6 Qxa6 35. Rxa6 Be6 36. a4 d3 37. Rd2 Rd4 38. f3
Bd5 39. Bxd5 R8xd5 40. Kf2 Rc4 41. a5 Ra4 42. Rc6 Ra3 43. Rc1 h5 44. Rcd1
Kg7 45. a6 g5 46. a7 Rxa7 47. Rxd3 Ra2+ 48. Kg1 Rxd3 49. Rxd3 Kg6 50. Kh2
Ra4 51. Rd5 g4 52. fxg4 hxg4 53. g3 Kf6 54. Rd7 Ke5 55. Kg2 f5 56. Rd2 Rc4
57. Re2+ Kd4 58. Rf2 Rc5 59. Rf4+ Ke3 60. Kg1 1/2-1/2
[Event "Leipzig Olympiad Final"]
[Site "?"]
[Date "1960"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Euwe, Max"]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Nc6 6. Nf3 Bg4 7. cxd5 Nxd5
8. Qb3 Bxf3 9. gxf3 e6 10. Qxb7 Nxd4 11. Bb5+ Nxb5 12. Qc6+ Ke7 13. Qxb5
Nxc3 14. bxc3 Qd7 15. Rb1 Rd8 16. Be3 Qxb5 17. Rxb5 Rd7 18. Ke2 f6 19. Rd1
Rxd1 20. Kxd1 Kd7 21. Rb8 Kc6 22. Bxa7 g5 23. a4 Bg7 24. Rb6+ Kd5 25. Rb7
Bf8 26. Rb8 Bg7 27. Rb5+ Kc6 28. Rb6+ Kd5 29. a5 f5 30. Bb8 Rc8 31. a6 Rxc3
32. Rb5+ Kc4 33. Rb7 Bd4 34. Rc7+ Kd3 35. Rxc3+ Kxc3 36. Be5 1-0
[Event "Bled"]
[Site "?"]
[Date "1961"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d4 dxe4 7. Qe3 Nbd7
8. Nxe4 Nxe4 9. Qxe4 Nf6 10. Qd3 Qd5 11. c4 Qd6 12. Be2 e5 13. d5 e4 14.
Qc2 Be7 15. dxc6 Qxc6 16. O-O O-O 17. Be3 Bc5 18. Qc3 b6 19. Rfd1 Rfd8 20.
b4 Bxe3 21. fxe3 Qc7 22. Rd4 a5 23. a3 axb4 24. axb4 h5 25. Rad1 Rxd4 26.
Qxd4 Qg3 27. Qxb6 Ra2 28. Bf1 h4 29. Qc5 Qf2+ 30. Kh1 g6 31. Qe5 Kg7 32. c5
Qxe3 33. c6 Rc2 34. b5 Rc1 35. Rxc1 Qxc1 36. Kg1 e3 37. c7 e2 38. Qxe2 Qxc7
39. Qf2 g5 40. b6 Qe5 41. b7 Nd7 42. Qd2 Nb8 43. Be2 Kf6 44. Bf3 Ke6 45.
Bg4+ f5 46. Bd1 Kf6 47. Qd8+ Kg6 48. Qg8+ Kh6 49. Qf8+ Kg6 50. Qg8+ Kh6 51.
Qf8+ Kg6 52. Qb4 Nc6 53. Qd2 Nd8 54. Bf3 Nxb7 55. Bxb7 Qa1+ 56. Kh2 Qe5+
1/2-1/2
[Event "Bled"]
[Site "?"]
[Date "1961"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Nf3 Ngf6 6. Nxf6+ Nxf6 7. Bc4
Bf5 8. Qe2 e6 9. Bg5 Bg4 10. O-O-O Be7 11. h3 Bxf3 12. Qxf3 Nd5 13. Bxe7
Qxe7 14. Kb1 Rd8 15. Qe4 b5 16. Bd3 a5 17. c3 Qd6 18. g3 b4 19. c4 Nf6 20.
Qe5 c5 21. Qg5 h6 22. Qxc5 Qxc5 23. dxc5 Ke7 24. c6 Rd6 25. Rhe1 Rxc6 26.
Re5 Ra8 27. Be4 Rd6 28. Bxa8 Rxd1+ 29. Kc2 Rf1 30. Rxa5 Rxf2+ 31. Kb3 Rh2
32. c5 Kd8 33. Rb5 Rxh3 34. Rb8+ Kc7 35. Rb7+ Kc6 36. Kc4 1-0
[Event "Stockholm Interzonal"]
[Site "?"]
[Date "1962"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Barcza, Gedeon"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. d4 Bd6 7. Bc4
O-O 8. O-O Re8 9. Bb3 Nd7 10. Nh4 Nf8 11. Qd3 Bc7 12. Be3 Qe7 13. Nf5 Qe4
14. Qxe4 Rxe4 15. Ng3 Re8 16. d5 cxd5 17. Bxd5 Bb6 18. Bxb6 axb6 19. a3 Ra5
20. Rad1 Rc5 21. c3 Rc7 22. Bf3 Rd7 23. Rxd7 Nxd7 24. Nf5 Nc5 25. Nd6 Rd8
26. Nxc8 Rxc8 27. Rd1 Kf8 28. Rd4 Rc7 29. h3 f5 30. Rb4 Nd7 31. Kf1 Ke7 32.
Ke2 Kd8 33. Rb5 g6 34. Ke3 Kc8 35. Kd4 Kb8 36. Kd5 Rc6 37. Kd4 Re6 38. a4
Kc7 39. a5 Rd6+ 40. Bd5 Kc8 41. axb6 f6 42. Ke3 Nxb6 43. Bg8 Kc7 44. Rc5+
Kb8 45. Bxh7 Nd5+ 46. Kf3 Ne7 47. h4 b6 48. Rb5 Kb7 49. h5 Ka6 50. c4 gxh5
51. Bxf5 Rd4 52. b3 Nc6 53. Ke3 Rd8 54. Be4 Na5 55. Bc2 h4 56. Rh5 Re8+ 57.
Kd2 Rg8 58. Rxh4 b5 59. Rf4 bxc4 60. bxc4 Rxg2 61. Rxf6+ Ka7 62. Kc3 Rg4
63. f4 Nb7 64. Kb4 1-0
[Event "Varna Olympiad Final"]
[Site "?"]
[Date "1962"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Donner, Jan H."]
[Result "0-1"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 h6 7. Nf3 Nd7 8.
Bd3 Bxd3 9. Qxd3 e6 10. Bf4 Qa5+ 11. Bd2 Qc7 12. c4 Ngf6 13. Bc3 a5 14. O-O
Bd6 15. Ne4 Nxe4 16. Qxe4 O-O 17. d5 Rfe8 18. dxc6 bxc6 19. Rad1 Bf8 20.
Nd4 Ra6 21. Nf5 Nc5 22. Qe3 Na4 23. Be5 Qa7 24. Nxh6+ gxh6 25. Rd4 f5 26.
Rfd1 Nc5 27. Rd8 Qf7 28. Rxe8 Qxe8 29. Bd4 Ne4 30. f3 e5 31. fxe4 exd4 32.
Qg3+ Bg7 33. exf5 Qe3+ 34. Qxe3 dxe3 35. Rd8+ Kf7 36. Rd7+ Kf6 37. g4 Bf8
38. Kg2 Bc5 39. Rh7 Ke5 40. Kf3 Kd4 41. Rxh6 Rb6 42. b3 a4 43. Re6 axb3 44.
axb3 Kd3 0-1
[Event "USA Championship"]
[Site "?"]
[Date "1963"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Steinmeyer, Robert H."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nf3 Nf6 7. h4 h6 8.
Bd3 Bxd3 9. Qxd3 e6 10. Bd2 Nbd7 11. O-O-O Qc7 12. c4 O-O-O 13. Bc3 Qf4+
14. Kb1 Nc5 15. Qc2 Nce4 16. Ne5 Nxf2 17. Rdf1 1-0
[Event "Skopje"]
[Site "?"]
[Date "1967"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Panov, Vasil"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. Bc4 Bd6 7. O-O
O-O 8. d4 Be6 9. Bxe6 fxe6 10. Re1 Re8 11. c4 Na6 12. Bd2 Qd7 13. Bc3 Bb4
14. Qb3 Bxc3 15. bxc3 Nc7 16. a4 b6 17. h3 Rab8 18. Re4 a6 19. Qc2 b5 20.
axb5 axb5 21. cxb5 cxb5 22. Nd2 Ra8 23. Rae1 Qd5 24. Rh4 Qf5 25. Ne4 e5 26.
Re3 h6 27. Rf3 Qh7 28. Nxf6+ gxf6 29. Rg3+ Kh8 30. Rg6 1-0
[Event "Nathania"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Cagan, Shimon"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. a3 Nbd7 8.
g4 Bd6 9. g5 Ng8 10. h4 Ne7 11. h5 Qb6 12. Bh3 O-O-O 13. a4 a5 14. O-O Rhf8
15. Kh1 f5 16. Qg2 g6 17. h6 Kb8 18. f4 Rfe8 19. e5 Bc5 20. Qf3 Nc8 21. Bg2
Kc7 22. Ne2 Nb8 23. c3 Kd7 24. Bd2 Na6 25. Rfb1 Bf8 26. b4 axb4 27. cxb4
Bxb4 28. a5 Qc5 29. d4 Qf8 30. Bxb4 Nxb4 31. Qc3 Na6 32. Rxb7+ Nc7 33. Nc1
Re7 34. a6 1-0
[Event "Nathania"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Czerniak, Moshe"]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Bd3 Nc6 5. c3 Nf6 6. Bf4 g6 7. Nf3 Bg7 8.
Nbd2 Nh5 9. Be3 O-O 10. O-O f5 11. Nb3 Qd6 12. Re1 f4 13. Bd2 Bg4 14. Be2
Rae8 15. Nc1 Bxf3 16. Bxf3 e5 17. Qb3 exd4 18. Nd3 Rd8 19. c4 dxc4 20.
Qxc4+ Kh8 21. Re6 Qb8 22. Rae1 Rc8 23. Bxc6 Rxc6 24. Rxc6 bxc6 25. Qxc6 Qc8
26. Qxc8 Rxc8 27. Kf1 Bh6 28. Rc1 Rxc1+ 29. Bxc1 g5 30. b4 Kg8 31. b5 Kf7
32. Ba3 Bf8 33. Ne5+ Ke6 34. Bxf8 Kxe5 35. Bc5 Nf6 36. Bxa7 Ne4 37. f3 Nd2+
38. Ke2 Nc4 39. b6 Na5 40. b7 Nxb7 41. Kd3 h5 42. Bxd4+ Kd5 43. h3 Nd8 44.
a4 Ne6 45. Bb6 g4 46. hxg4 hxg4 47. fxg4 1-0
[Event "Nathania"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Yanofsky, Daniel A."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 g6 6. Qb3 Bg7 7. cxd5 O-O
8. Be2 Na6 9. Bg5 Qb6 10. Qxb6 axb6 11. a3 Rd8 12. Bxf6 Bxf6 13. Rd1 Bf5
14. Bc4 Rac8 15. Bb3 b5 16. Nf3 b4 17. axb4 Nxb4 18. Ke2 Bc2 19. Bxc2 Nxc2
20. Kd3 Nb4+ 21. Ke4 Rd6 22. Ne5 Bg7 23. g4 f5+ 24. gxf5 gxf5+ 25. Kf4 Rf8
26. Rhg1 Nxd5+ 27. Nxd5 Rxd5 28. Nf3 Kh8 29. Rge1 Bf6 30. Ne5 e6 31. h4 Rc8
32. Nf7+ Kg7 33. Ng5 Bxg5+ 34. Kxg5 Rc6 35. Re5 Rcd6 36. Rxd5 Rxd5 37. f4
Rb5 38. Rd2 Rb3 39. d5 h6+ 40. Kh5 exd5 41. Rxd5 Rxb2 42. Rd7+ Kf6 43. Rd6+
Kf7 44. Rxh6 Rg2 45. Rb6 Rg4 46. Rxb7+ Kf6 1/2-1/2
[Event "Vinkovci"]
[Site "?"]
[Date "1968"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Hort, Vlastimil"]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Nf3 Nf6 5. c3 Bf5 6. Bb5+ Nbd7 7. Nh4 Bg6
8. Bf4 e6 9. Nd2 Nh5 10. Nxg6 hxg6 11. Be3 Bd6 12. g3 a6 13. Bd3 Rc8 14.
O-O Nb6 15. a4 Rc7 16. Qb3 Nc8 17. c4 dxc4 18. Nxc4 Nf6 19. Rac1 O-O 20.
Bd2 Nd5 21. Be4 Be7 22. Na5 Ncb6 23. Bxd5 Nxd5 24. Nxb7 Qb8 25. Rxc7 Qxc7
26. Rc1 Qb8 27. Rc4 Rd8 28. Bc3 Rd7 29. Na5 Qxb3 30. Rc8+ Kh7 31. Nxb3 Nb6
32. Rc6 Nxa4 33. Rxa6 Nxc3 34. bxc3 Rc7 35. Nd2 Rxc3 36. Ra7 Rd3 37. Nf1
Bf6 38. Rxf7 Rxd4 39. Kg2 g5 40. h3 Kg6 41. Rc7 Ra4 42. Nd2 Rd4 43. Nb3 Rd6
44. Nc5 Kf5 45. Kf3 Rb6 46. Rd7 Rc6 47. Ne4 Ra6 48. Rd3 Be7 49. Rb3 Ra3 50.
Rxa3 Bxa3 51. g4+ Kg6 52. Ke3 Bc1+ 53. Kd4 Bf4 54. Kc5 Kf7 55. Kb6 Ke8 56.
Kc6 Ke7 1/2-1/2
[Event "Palma de Mallorca"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Hubner, Robert"]
[Result "1/2-1/2"]
1. e4 c6 2. d3 d5 3. Nd2 g6 4. g3 Bg7 5. Bg2 e5 6. Ngf3 Ne7 7. O-O O-O 8.
Re1 d4 9. a4 c5 10. Nc4 Nbc6 11. c3 Be6 12. cxd4 Bxc4 13. dxc4 exd4 14. e5
Qd7 15. h4 d3 16. Bd2 Rad8 17. Bc3 Nb4 18. Nd4 Rfe8 19. e6 fxe6 20. Nxe6
Bxc3 21. bxc3 Nc2 22. Nxd8 Rxd8 23. Qd2 Nxa1 24. Rxa1 Kg7 25. Re1 Ng8 26.
Bd5 Qxa4 27. Qxd3 Re8 28. Rxe8 Qxe8 29. Bxb7 Nf6 30. Qd6 Qd7 31. Qa6 Qf7
32. Qxa7 Ne4 33. f3 Nd6 34. Qxc5 Nxb7 35. Qd4+ Kg8 36. Kf2 Qe7 37. Qd5+ Kf8
38. h5 gxh5 39. Qxh5 Nc5 40. Qd5 Kg7 41. Qd4+ Kf7 42. Qd5+ Kg7 43. Qd4+ Kf7
44. Qd5+ 1/2-1/2
[Event "Siegen Olympiad Final"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Hort, Vlastimil"]
[Result "1/2-1/2"]
1. e4 c6 2. d3 d5 3. Nd2 g6 4. g3 Bg7 5. Bg2 e5 6. Ngf3 Ne7 7. O-O O-O 8.
Re1 Nd7 9. b3 d4 10. Bb2 b5 11. c3 c5 12. Rc1 Bb7 13. cxd4 cxd4 14. Bh3 Nc6
15. a3 Re8 16. Qe2 Rc8 17. Rc2 Ne7 18. Rec1 Rxc2 19. Rxc2 Nc6 20. Qd1 Nb6
21. Qc1 Qf6 22. Bg2 Rc8 23. h4 Bf8 24. Bh3 Rc7 25. Nh2 Bc8 26. Bf1 Bd7 27.
h5 Rc8 28. Be2 Nd8 29. Rxc8 Bxc8 30. Ndf3 Nc6 31. Nh4 b4 32. axb4 Nxb4 33.
N4f3 a5 34. Qc7 Qd6 35. Qa7 Ba6 36. Ba3 Nc8 37. Qa8 Qb6 38. Bxb4 Bxb4 39.
Qd5 Qc5 40. Qxe5 Qxe5 41. Nxe5 Nd6 42. hxg6 hxg6 43. Kf1 Bb5 44. Nhf3 Bc3
45. Ne1 Nb7 46. Bd1 Nc5 47. f3 Kg7 48. Bc2 Kf6 49. Ng4+ Ke7 50. Nf2 Bd7 51.
Nd1 Bb4 52. Nb2 Be6 53. Nc4 Bxc4 54. dxc4 Bxe1 55. Kxe1 g5 56. Ke2 Kd6 57.
f4 gxf4 58. gxf4 f6 59. Kf3 Ke6 60. Ke2 Kd6 1/2-1/2
[Event "Siegen Olympiad Prelim"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Ibrahimoglu, Ismet"]
[Result "1-0"]
1. e4 c6 2. d3 d5 3. Nd2 g6 4. Ngf3 Bg7 5. g3 Nf6 6. Bg2 O-O 7. O-O Bg4 8.
h3 Bxf3 9. Qxf3 Nbd7 10. Qe2 dxe4 11. dxe4 Qc7 12. a4 Rad8 13. Nb3 b6 14.
Be3 c5 15. a5 e5 16. Nd2 Ne8 17. axb6 axb6 18. Nb1 Qb7 19. Nc3 Nc7 20. Nb5
Qc6 21. Nxc7 Qxc7 22. Qb5 Ra8 23. c3 Rxa1 24. Rxa1 Rb8 25. Ra6 Bf8 26. Bf1
Kg7 27. Qa4 Rb7 28. Bb5 Nb8 29. Ra8 Bd6 30. Qd1 Nc6 31. Qd2 h5 32. Bh6+ Kh7
33. Bg5 Rb8 34. Rxb8 Nxb8 35. Bf6 Nc6 36. Qd5 Na7 37. Be8 Kg8 38. Bxf7+
Qxf7 39. Qxd6 1-0
[Event "USSR-World"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1-0"]
1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Bd3 Nc6 5. c3 Nf6 6. Bf4 Bg4 7. Qb3 Na5
8. Qa4+ Bd7 9. Qc2 e6 10. Nf3 Qb6 11. a4 Rc8 12. Nbd2 Nc6 13. Qb1 Nh5 14.
Be3 h6 15. Ne5 Nf6 16. h3 Bd6 17. O-O Kf8 18. f4 Be8 19. Bf2 Qc7 20. Bh4
Ng8 21. f5 Nxe5 22. dxe5 Bxe5 23. fxe6 Bf6 24. exf7 Bxf7 25. Nf3 Bxh4 26.
Nxh4 Nf6 27. Ng6+ Bxg6 28. Bxg6 Ke7 29. Qf5 Kd8 30. Rae1 Qc5+ 31. Kh1 Rf8
32. Qe5 Rc7 33. b4 Qc6 34. c4 dxc4 35. Bf5 Rff7 36. Rd1+ Rfd7 37. Bxd7 Rxd7
38. Qb8+ Ke7 39. Rde1+ 1-0
[Event "USSR-World"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. d4 d5 3. Nc3 g6 4. e5 Bg7 5. f4 h5 6. Nf3 Bg4 7. h3 Bxf3 8.
Qxf3 e6 9. g3 Qb6 10. Qf2 Ne7 11. Bd3 Nd7 12. Ne2 O-O-O 13. c3 f6 14. b3
Nf5 15. Rg1 c5 16. Bxf5 gxf5 17. Be3 Qa6 18. Kf1 cxd4 19. cxd4 Nb8 20. Kg2
Nc6 21. Nc1 Rd7 22. Qd2 Qa5 23. Qxa5 Nxa5 24. Nd3 Nc6 25. Rac1 Rc7 26. Rc3
b6 27. Rgc1 Kb7 28. Nb4 Rhc8 29. Rxc6 Rxc6 30. Rxc6 Rxc6 31. Nxc6 Kxc6 32.
Kf3 1/2-1/2
[Event "Zabreb"]
[Site "?"]
[Date "1970"]
[Round "?"]
[White "Fischer, Robert J."]
[Black "Marovic, Drazen"]
[Result "1-0"]
1. e4 c6 2. d3 d5 3. Nd2 Nd7 4. Ngf3 Qc7 5. exd5 cxd5 6. d4 g6 7. Bd3 Bg7
8. O-O e6 9. Re1 Ne7 10. Nf1 Nc6 11. c3 O-O 12. Bg5 e5 13. Ne3 Nb6 14. dxe5
Nxe5 15. Bf4 f6 16. a4 Qf7 17. a5 Nbc4 18. Bxc4 dxc4 19. Bxe5 fxe5 20. Qe2
h6 21. Nxc4 Bg4 22. Ncxe5 Bxe5 23. Nxe5 Bxe2 24. Nxf7 Rxf7 25. Rxe2 Rd8 26.
Rae1 Rd5 27. b4 Rc7 28. Re3 Kf7 29. h4 Rd2 30. Rf3+ Kg7 31. Re6 Rf7 32.
Rxf7+ Kxf7 33. Re5 Rd1+ 34. Kh2 b6 35. axb6 axb6 36. f3 Rd3 37. Rb5 Rxc3
38. Rxb6 h5 39. Rb7+ Kf6 40. b5 Rb3 41. b6 Rb4 42. Kg3 Rb2 43. Rb8 Kg7 44.
f4 Rb3+ 45. Kf2 Kf6 46. Ke2 Kg7 47. Kd2 Rg3 48. Rc8 1-0
[Event "?"]
[Site "Stockholm"]
[Date "1962.??.??"]
[Round "4"]
[White "Fischer, Robert J."]
[Black "Portisch, Lajos"]
[Result "1-0"]
1. e4 c6 2. Nc3 d5 3. Nf3 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Neg5 Nd5 7. d4 h6
8. Ne4 N7b6 9. Bb3 Bf5 10. Ng3 Bh7 11. O-O e6 12. Ne5 Nd7 13. c4 N5f6 14.
Bf4 Nxe5 15. Bxe5 Bd6 16. Qe2 O-O 17. Rad1 Qe7 18. Bxd6 Qxd6 19. f4 c5 20.
Qe5 Qxe5 21. dxe5 Ne4 22. Rd7 Nxg3 23. hxg3 Be4 24. Ba4 Rad8 25. Rfd1 Rxd7
26. Rxd7 g5 27. Bd1 Bc6 28. Rd6 Rc8 29. Kf2 Kf8 30. Bf3 Bxf3 31. gxf3 gxf4
32. gxf4 Ke7 33. f5 exf5 34. Rxh6 Rd8 35. Ke2 Rg8 36. Kf2 Rd8 37. Ke3 Rd1
38. b3 Re1+ 39. Kf4 Re2 40. Kxf5 Rxa2 41. f4 Re2 42. Rh3 Re1 43. Rd3 Rb1
44. Re3 Rb2 45. e6 a6 46. exf7+ Kxf7 47. Ke5 Rd2 48. Rc3 b6 49. f5 Rd1 50.
Rh3 b5 51. Rh7+ Kg8 52. Rb7 bxc4 53. bxc4 Rd4 54. Ke6 Re4+ 55. Kd5 Rf4 56.
Kxc5 Rxf5+ 57. Kd6 Rf6+ 58. Ke5 Rf7 59. Rb6 Rc7 60. Kd5 Kf7 61. Rxa6 Ke7
62. Re6+ Kd8 63. Rd6+ Ke7 64. c5 Rc8 65. c6 Rc7 66. Rh6 Kd8 67. Rh8+ Ke7
68. Ra8 1-0
[Event "?"]
[Site "Yugoslavia ct"]
[Date "1959.??.??"]
[Round "2"]
[White "Fischer, Robert J."]
[Black "Keres, Paul"]
[Result "0-1"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Qb6 10. b3 a5 11. a3 Be7 12. Bg2 a4 13. b4 Nbd7 14. O-O c5
15. Ra2 O-O 16. bxc5 Bxc5 17. Qe2 e5 18. f4 Rfc8 19. h4 Rc6 20. Bh3 Qc7 21.
fxe5 Nxe5 22. Bf4 Bd6 23. h5 Ra5 24. h6 Ng6 25. Qf3 Rh5 26. Bg4 Nxf4 27.
Bxh5 N4xh5 28. Kg2 Ng4 29. Nd2 Ne3+ 0-1
[Event "?"]
[Site "Yugoslavia ct"]
[Date "1959.??.??"]
[Round "3"]
[White "Fischer, Robert J."]
[Black "Petrosian, Tigran V."]
[Result "1/2-1/2"]
1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 4. h3 Bxf3 5. Qxf3 Nf6 6. d3 e6 7. g3 Bb4 8.
Bd2 d4 9. Nb1 Bxd2+ 10. Nxd2 e5 11. Bg2 c5 12. O-O Nc6 13. Qe2 Qe7 14. f4
O-O-O 15. a3 Ne8 16. b4 cxb4 17. Nc4 f6 18. fxe5 fxe5 19. axb4 Nc7 20. Na5
Nb5 21. Nxc6 bxc6 22. Rf2 g6 23. h4 Kb7 24. h5 Qxb4 25. Rf7+ Kb6 26. Qf2 a5
27. c4 Nc3 28. Rf1 a4 29. Qf6 Qc5 30. Rxh7 Rdf8 31. Qxg6 Rxh7 32. Qxh7
Rxf1+ 33. Bxf1 a3 34. h6 a2 35. Qg8 a1=Q 36. h7 Qd6 37. h8=Q Qa7 38. g4 Kc5
39. Qf8 Qae7 40. Qa8 Kb4 41. Qh2 Kb3 42. Qa1 Qa3 43. Qxa3+ Kxa3 44. Qh6 Qf7
45. Kg2 Kb3 46. Qd2 Qh7 47. Kg3 Qxe4 48. Qf2 Qh1 1/2-1/2

View File

@@ -0,0 +1,11 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4
{ only-a-fool-would-play-this-move-and-only-someone-wanting-to-test-how-the-program-copes-with-very-long-lines-would-type-a-comment-like-this }
Qh4# 0-1

View File

@@ -0,0 +1,17 @@
[Event "Kopavogur International Tournament"]
[Site "Kopavogur ICE"]
[Date "1994.04.16"]
[Round "8"]
[White "Stefansson, Hannes"]
[Black "Olafsson, Helgi"]
[Result "1/2-1/2"]
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 e6 7. f3 Nbd7 8.
g4 h6 9. Qd2 b5 10. O-O-O b4 11. Nce2 d5 12. Nf4 dxe4 13. Ndxe6 fxe6 14.
Bc4 Qc7 15. Bxe6 Ne5 16. Bb3 Bd7 17. fxe4 Bc5 18. Bxc5 Qxc5 19. Nd3 Nxd3+
20. Qxd3 O-O-O 21. e5 Bb5 22. Qf5+ Nd7 23. Rd5 Qe3+ 24. Kb1 Rhf8 25. Qg6
Nc5 26. Qxg7 Nxb3 27. axb3 Bc6 28. Rxd8+ Rxd8 29. Rf1 Be4 30. Qf6 Qe2 31.
Qe6+ Rd7 32. Rc1 Kc7 33. h4 a5 34. g5 hxg5 35. hxg5 Rd1 36. Qe7+ Kb6 37.
Qe6+ Kc7 38. Qe7+ Kb6 39. Qe6+ Bc6 40. Rxd1 Qxd1+ 41. Ka2 Qxc2 42. Qd6 Qc5
43. Qb8+ Bb7 44. g6 a4 45. Qd8+ Ka7 46. Qd7 Kb6 47. Qd8+ Ka6 48. Qd3+ Ka5
49. Qd8+ Ka6 50. Qd3+ Ka7 51. Qd7 Kb6 1/2-1/2

View File

@@ -0,0 +1 @@
b3 { good or bad? } $1 { some think this is good } $2 { while others think it is not } *

View File

@@ -0,0 +1,9 @@
[Result "1-0"] e4 *
[Result "0-1"] e4 *
[Result "1/2-1/2"] e4 *
[Result "1-0"] e4 0-1
[Result "0-1"] e4 1/2-1/2
[Result "1/2-1/2"] e4 1-0
[Result "*"] e4 1-0
[Result "*"] e4 0-1
[Result "*"] e4 1/2-1/2

View File

@@ -0,0 +1,28 @@
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "0-1"]
1. f3 e5 2. g4 Qh4# 0-1
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,18 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {Time control} 1/2-1/2

View File

@@ -0,0 +1,18 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {Time control} 1/2-1/2

View File

@@ -0,0 +1,18 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 {Time control} 1/2-1/2

View File

@@ -0,0 +1,6 @@
b2b3 e7e5 c1b2 d7d6 d2d4 e5d4 d1d4 b8c6 d4d2 g8f6 b1c3 c8e6 e2e4 d6d5 e4d5
e6d5 d2e3+ f8e7 g1f3 e8g8 f1e2 f8e8 e1c1 e7b4 e3d3 b4c3 b2c3 d8e7 h1e1 f6e4
c3b2 a8d8 d3e3 b7b6 e2b5 e7e6 f3d4 c6d4 d1d4 c7c5 d4e4 d5e4 b5e8 d8e8 f2f3
e4d5 e3e6 e8e6 e1e6 d5e6 c1d2 g8f8 b2e5 b6b5 e5b8 a7a6 b8a7 c5c4 d2c3 f8e7
c3d4 e7d6 a7c5+ d6d7 c5a7 d7d6 a7c5+ d6d7 d4c3 g7g6 c5d4 f7f5 1/2-1/2

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,19 @@
[Event "Dover vs Herne Bay, Minor League"]
[Site "Margate Chess Club"]
[Date "1994.10.10"]
[Round ""]
[White "Barnes, David J."]
[Black "Horton, Mark"]
[Result "1/2-1/2"]
{ Game played inaccurately by White under extreme time pressure. }
1. b3 e5 2. Bb2 d6 3. d4 exd4 4. Qxd4 Nc6 5. Qd2 Nf6 6. Nc3 Be6 7. e4 d5 8.
exd5 Bxd5 9. Qe3+ Be7 10. Nf3 O-O 11. Be2 Re8 12. O-O-O Bb4 13. Qd3 Bxc3
14. Bxc3 Qe7 15. Rhe1 Ne4 16. Bb2 Rad8 17. Qe3 b6 18. Bb5 Qe6 19. Nd4 Nxd4
20. Rxd4 c5 21. Rxe4 Bxe4 22. Bxe8 { 2 minutes to time-control at move 36.
} 22... Rxe8 23. f3 Bd5 24. Qxe6 Rxe6 25. Rxe6 Bxe6 26. Kd2 Kf8 27. Be5 b5
28. Bb8 $2 (28. Bd6+ { wins }) 28... a6 29. Ba7 c4 30. Kc3 Ke7 31. Kd4 Kd6
32. Bc5+ Kd7 33. Ba7 Kd6 34. Bc5+ Kd7 35. Kc3 g6 36. Bd4 f5 { Time control.
} 1/2-1/2

View File

@@ -0,0 +1,41 @@
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8R 1-0
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8N *
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8B *
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8Q 1-0
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8r 1-0
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8n *
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8b *
[FEN "7k/3P4/7K/8/8/8/8/8 w - - 6 55"]
[SetUp "1"]
d7d8q 1-0

Some files were not shown because too many files have changed in this diff Show More