From e597a4014df46fbc2b8cacc74f8f176c194872a0 Mon Sep 17 00:00:00 2001 From: Luis Felipe Strano Moraes Date: Tue, 13 Mar 2012 13:20:44 -0300 Subject: [PATCH] Initial commit based on GNU Shogi 1.2 patchlevel 3. This is based on the release made by Matthias Mutz (mutz@fmi.uni-passau.de). --- README-1.2p03 | 19 + doc/BOOKFILES | 93 ++ doc/CHANGES | 50 + doc/CONTRIB | 4 + doc/COPYING | 339 ++++++ doc/GENERAL | 56 + doc/INSTALL | 27 + doc/PORTING | 42 + doc/README-FIRST | 17 + doc/gnushogi.1 | 432 ++++++++ doc/listserv.ref | 63 ++ doc/shogi.rules | 117 ++ doc/tutorial1.gam | 113 ++ doc/tutorial2.gam | 125 +++ misc/gnushogi.lng | 234 ++++ misc/gnushogi.pat | 167 +++ misc/gnushogi.tbk | 3170 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/.LVS_ENV | 1 + src/Makefile | 456 ++++++++ src/ataks.c | 342 ++++++ src/book.c | 931 ++++++++++++++++ src/book.h | 60 + src/dspcom.c | 2147 ++++++++++++++++++++++++++++++++++++ src/eval.c | 3128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/eval.h | 59 + src/genmove.c | 1478 +++++++++++++++++++++++++ src/globals.c | 176 +++ src/gnushogi.h | 1155 +++++++++++++++++++ src/init.c | 1146 +++++++++++++++++++ src/main.c | 372 +++++++ src/nondsp.c | 831 ++++++++++++++ src/pat2inc.c | 129 +++ src/pattern.c | 1002 +++++++++++++++++ src/pattern.h | 120 ++ src/pattern.inc | 166 +++ src/search.c | 1787 ++++++++++++++++++++++++++++++ src/sizetest.c | 293 +++++ src/tcontrl.c | 302 +++++ src/util.c | 605 ++++++++++ src/uxdsp.c | 1050 ++++++++++++++++++ src/version.h | 10 + 41 files changed, 22814 insertions(+), 0 deletions(-) create mode 100644 README-1.2p03 create mode 100644 doc/BOOKFILES create mode 100644 doc/CHANGES create mode 100644 doc/CONTRIB create mode 100644 doc/COPYING create mode 100644 doc/GENERAL create mode 100644 doc/INSTALL create mode 100644 doc/PORTING create mode 100644 doc/README-FIRST create mode 100644 doc/gnushogi.1 create mode 100644 doc/listserv.ref create mode 100644 doc/shogi.rules create mode 100644 doc/tutorial1.gam create mode 100644 doc/tutorial2.gam create mode 100644 misc/gnushogi.lng create mode 100644 misc/gnushogi.pat create mode 100644 misc/gnushogi.tbk create mode 100644 src/.LVS_ENV create mode 100644 src/Makefile create mode 100644 src/ataks.c create mode 100644 src/book.c create mode 100644 src/book.h create mode 100644 src/dspcom.c create mode 100644 src/eval.c create mode 100644 src/eval.h create mode 100644 src/genmove.c create mode 100644 src/globals.c create mode 100644 src/gnushogi.h create mode 100644 src/init.c create mode 100644 src/main.c create mode 100644 src/nondsp.c create mode 100644 src/pat2inc.c create mode 100644 src/pattern.c create mode 100644 src/pattern.h create mode 100644 src/pattern.inc create mode 100644 src/search.c create mode 100644 src/sizetest.c create mode 100644 src/tcontrl.c create mode 100644 src/util.c create mode 100644 src/uxdsp.c create mode 100644 src/version.h diff --git a/README-1.2p03 b/README-1.2p03 new file mode 100644 index 0000000..c71e9b5 --- /dev/null +++ b/README-1.2p03 @@ -0,0 +1,19 @@ +Hello, + +this is GNU Shogi 1.2 patchlevel 3. There are only minor +changes of the patchlevel 2 version. Some bugs have been +removed. + +For installation procedure read doc/INSTALL. + +You cannot use the binary book file from previous versions, +you have to rebuild it. + +You may email discovered bugs or comments to me. + +Have fun, + + Matthias Mutz. + +email: mutz@fmi.uni-passau.de + diff --git a/doc/BOOKFILES b/doc/BOOKFILES new file mode 100644 index 0000000..1571cd4 --- /dev/null +++ b/doc/BOOKFILES @@ -0,0 +1,93 @@ +Binary book files +----------------- + +In GNU Shogi the book file is a binary file. +The binary book file is "gnushogi.bbk". +It is intended that text book files will only be +used to generate the binary file (see remarks about syntax below). + +The Makefile will generate a "gnushogi.bbk" in the "src" directory +from the text book file "gnushogi.tbk" in the "misc" directory +if "make gnushogi.bbk" is entered (the "gnushogir" executable +must be available in the "src" directory or it is created). + +"make install" also copies the "gnushogi.bbk" to the installation +directory for libraries. + +Adding new opening lines +------------------------ + +You can add entries to the binary file by providing a text book +file "gnushogi.tbk" in the installation directory. +After starting gnushogi, the new entries will be added. It is +recommended to remove the text book file after adding the entries to +the binary book file (or gnushogi will always check for new entries). + +You can also use the "bsave" command while running gnushogi. The current +moves will be appended to the named file in a text book file style. + +Syntax of text book files +------------------------- + +Text book files are used to generate the binary book file. You must follow a +special text book file syntax while adding an opening line. The book file +parser (program that interpretes the text book moves) is abble to accept +several common Shogi notations. +It also allows to include comments. + +All characters in a line following a '#' character are comments. +The moves of an opening line is always between two lines with a '#' as its first +character. So, you must not use 1st-column-'#'-comments to give comments to an +opening line. "in-opening" comments are included in brackets ('[' ... ']'). +After each ply, you can add a comment in parantheses ('(' ... ')'). +This is normally used in Shogi notations to indicate the amount of time used by +the player to enter that move. + +There are several possibilites to describe a move. Examples are + + 7g7f P7f P7g-7f P-7f + 3c3d +B3cx3d +Bx3d +B3d + 2d2c+ P2c+ P2dx2c+ Px2c+ + +When you use a character to indicate the piece type, you have to observe +whether the piece is promoted or not, i.e for a promoted piece you have to +indicate this using a '+'. In Shogi notations, the '+' for promoted pieces +may be important in order to avoid ambiguities. + +For example + + # + # Double Fortess + P7f P8d + [ this is an "in-opening" comment ] + S6h P8e(1) + # this is an "off-opening" comment + +defines an opening line with two moves (four plys). The first comment line +above an opening line serves as the name of the opening line. This name is +used in case of errors in the opening line. + +You can use move numbers given as a decimal number followed by a '.'. + +You can indicate good and bad moves using the character combinations + ? ?? ?! ! !! !? !?/?! ?!/!? +They have the same meaning as in chess. The characters must directly follow +a move, i.e. there must be no spaces between the move and the bad/good +indicator. + P5e-5d? is correct, while P5e-5d ? is incorrect. +The indicators can be seen as a comment with one exception: if the first +character of the indicator is a '?', the move is marked as BAD_MOVE by the +program and it is not used by the computer if the computer has the option +to make this move. + +You can add some words which indicate the end of a game. These words are + Resigns Sennichite Jishogi 1-0 0-1 +"Sennichite" means "draw by repitition and "Jishogi" means "impasse". + +Request +------- + +If you add new opening lines, please make them available to the +GNU Shogi community. Thank you. + + diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 0000000..5e59a0c --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,50 @@ +ChangeLog will start with GNU Shogi 1.0 patchlevel 11 (04/07/1993) + +version 1.2 patchlevel 2 -> version 1.2 patchlevel 3 + ../05/1995 + correct connection to xshogi + correct creation of binary book file + better support of unsigned characters + +version 1.1 patchlevel 2 -> version 1.2 patchlevel 1 +version 1.2 patchlevel 1 -> version 1.2 patchlevel 2 + 13/09/1994 + change 'reachedGameCnt' from small_short to short in "pattern.h" + change "dspcom.c" for Illegal move support of xshogi + 24/09/1994 + change "genmove.c" in order to allow "stupid" non-promotion moves + change "dspcom.c" in order to protocol "stupid" moves + +version 1.1 patchlevel 2 -> version 1.2 patchlevel 1 + ../09/1994 + several changes to evaluation functions and move generation; + language file and pattern file are made internal + +version 1.1 patchlevel 1 -> version 1.1 patchlevel 2 + 10/06/1993 + correcting bug: MakeMove no longer destroys the node->flags + 07/11/1993 + changes according to GnuChess 4.0pl62; + introducing "IsCheckmate" in order to forbid checkmates + by dropping a pawn (illegal move); + correcting bug: UnmakeMove no longer destroys the node->flags + (especially the "exact" flag) + 05/11/1993 + enabling draw by repetition detection + 04/29/1993 + correcting "save game" and "get game"; + introducing a "tsume" mode, which allows gnushogi especially + search for forced checkmates + +version 1.0 patchlevel 11 -> version 1.1 patchlevel 1 + 04/22/1993 + deep search cut in genmoves.c + 04/20/1993 + enable pattern related scoring in opening stage + 04/15/1993 + tuning "eval.c" + 04/14/1993 + correction for the "abs" function in "init.c" + 04/10/1993 + switches SAVE_PTYPE_DISTDATA and SAVE_DISTDATA for optional + space reductions. diff --git a/doc/CONTRIB b/doc/CONTRIB new file mode 100644 index 0000000..b802b91 --- /dev/null +++ b/doc/CONTRIB @@ -0,0 +1,4 @@ + +Sep 12, 1994 + Hiroshi Tsuda: some openings added to gnushogi.tbk + diff --git a/doc/COPYING b/doc/COPYING new file mode 100644 index 0000000..e77696a --- /dev/null +++ b/doc/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/doc/GENERAL b/doc/GENERAL new file mode 100644 index 0000000..d9df93b --- /dev/null +++ b/doc/GENERAL @@ -0,0 +1,56 @@ + GNU Shogi + +Copyright (C) 1993 Matthias Mutz + (Copying permission notice at the end.) + +GNU Shogi is your program (as long as you follow the copyright and +licensing rules listed in the file COPYING). Your contribution +inspire current and future software developers. + +This document +------------- +This document is not meant to be a an introduction to computer shogi. + +Current Distribution +-------------------- +The most recent distribution of GNU Shogi contains the following +main-level files and directories: + + Filename Purpose + ------------------------------------------------------ +doc: + +GENERAL ---------- general gnushogi documentation --------- +COPYING + +ChangeLog ----------- specific gnushogi documentation ---------- +CHANGES +BOOKFILES +INSTALL +PROBLEMS +TOTO +README-FIRST + +gnushogi.1 ---------- man pages ----------- + +misc: +*.book - opening book + +src: +Makefile - unix makefile + +ataks.c - sources for the shogi playing program +ataks.h +book.c +dspcom.c +eval.c +genmoves.c +init.c +main.c +gnushogi.h +search.c +util.c +version.h + +nondsp.c - ASCII interface for acsii terminal/ chesstool/ xboard +uxdsp.c - curses based user interface diff --git a/doc/INSTALL b/doc/INSTALL new file mode 100644 index 0000000..637132d --- /dev/null +++ b/doc/INSTALL @@ -0,0 +1,27 @@ +Installation procedure for GNU Shogi +------------------------------------ + +1. edit src/Makefile. For setting the paths, normally only + HOME or LIBDIR and BINDIR need to be changed. Setting CC + and CFLAGS sets C compiler and compiler options. + +2. type 'make gnushogir' to create plain dumb-terminal shogi. + +3. type 'make gnushogi.bbk' to create the binary book file. + +4. OPTIONAL: + type 'make gnushogi' to create cursed based shogi + +5. OPTIONAL: + type 'make gnushogix' to create xshogi based shogi. You may + use GNU XShogi as an X Windows based graphical interface to + GNU Shogi. GNU XShogi also supports the Internet Shogi + Server (ISS). + +6. type 'make install' to copy the binary book file to the libraries + destination directory and to copy the gnushogi* executables to + the binaries destination directory. + +7. OPTIONAL: + type 'make clean' to remove objects from destination source + directory. diff --git a/doc/PORTING b/doc/PORTING new file mode 100644 index 0000000..b647989 --- /dev/null +++ b/doc/PORTING @@ -0,0 +1,42 @@ + +This is a note how to port gnushogi to machines with scarce memory: +gnushogi minimal requirements are: + - approximately 200 kByte memory for the executable program. + - at least 300 kByte for data structures. +You dont want to port gnushogi to a machine with less memory than that. + +gnushogi is optmized for speed and that means that memory has been used +when there has been a tradeoff between memory usage and speed. If you intend +to run gnushogi on a machine with less than 4 Mbyte memory the size of some +data structures have to be reduced. Here is a list of the largest data +structures in gnushogi, their sizes and a small comment on what can +be done to reduce their size: + +ttable: 1.5 MByte (#define vttblsz ) +etab: 1.4 MByte (can be removed) +Tree: 42 kByte (change f,t to unsigned char) +history: 131 kByte (can be removed, not recommended) +nextpos: 98 kByte (nothing save rewiting all move generation) +nextdir: 98 kByte (nothing save rewiting all move generation) +distdata: 6 kByte (can be changed to a macro) +ptype_distdata: 98 kByte (can be changed to a procedure) +hashcode: 26 kByte (no reduction possible) + +First of all, start by reducing the transposition table size, this +is done by setting vttblsz in (gnushogi.h). If the transopsition table +does not fit entierly in memory it will have a detrimental effect on +performance. You can remove the transposition table by defining +compiler option NOTTABLE. +You can remove the static evaluation cache by omitting the compiler +option CACHE. +You can remove the history table by omitting the compiler option HISTORY +(NOT recommended). +If this isn`nt enough, reconsider if you really want to do this port. +There is`nt really that much to gain by changing the other +data structures. + +There are some switches in order to enable space reduction: + +#define SAVE_PTYPE_DISTDATA (replace ptype_distdata by a procedure) +#define SAVE_DISTDATA (replace distdata by a macro) + diff --git a/doc/README-FIRST b/doc/README-FIRST new file mode 100644 index 0000000..969351c --- /dev/null +++ b/doc/README-FIRST @@ -0,0 +1,17 @@ +GNU Shogi is the japanese version of chess. You can find the +rules of Shogi in "shogi.rules". This file and many other +shogi related stuff can be obtained from the SHOGI-L listserver (see +"listserv.ref"). + +GNU Shogi is based on GNU Chess 4.0, i.e. the first +version of GNU Shogi has been obtained by "simply" modifying +the chess-specific parts of GNU Chess 4.0. + +There are now major changes compared to GNU Chess. + +I would like to thank all people who have made the +sources of GNU Chess 4.0 available. + + Matthias Mutz. + (mutz@fmi.uni-passau.de) + diff --git a/doc/gnushogi.1 b/doc/gnushogi.1 new file mode 100644 index 0000000..0aa5821 --- /dev/null +++ b/doc/gnushogi.1 @@ -0,0 +1,432 @@ +.TH gnushogi 6 +.SH NAME +gnushogi \- Shogi +.SH SYNOPSIS +.B gnushogi +[ +.B [[-]a] +.B [-b bookfile] +.B [-B binbookfile] +.B [-h langfile] +.B [-L langfile] +.B [-r length] +.B [-s pathname] [-l pathname] +.B [-S binbooksize] +.B [-t] [-c size] +.B [-T size] +.B [-v] +.B [-x] +.B arg1 arg2 +] +.SH DESCRIPTION +.I Gnushogi +plays a game of japanese chess (shogi) against the user or it plays against itself. +.PP +At startup +.I Gnushogi +reads the +.I binbook +file if it is present. It then looks for a +.I book +file. If it is present it adds its contents to the +.I binbook +data. If the +.I binbook +file is writable a new combined +.I binbook +file is written. + +.PP +.I Gnushogi +is an updated version of the gnuchess program. +It has a simple alpha-numeric board display, +or it can be compiled for use with the +.B chesstool +program on a SUN workstation or with the +.B xshogi +program under X-windows. +The program gets its opening moves from the file +.B gnushogi.book +which is located in a directory specified in the makefile. +To invoke the program type: +.TP +.B gnushogi +- simple curses based version +.TP +.B gnuchessx +- xshogi compatible version +.SH TIME CONTROLS +.PP +If one argument is given, it is the search time per move in +[minutes:]seconds. +So +.B gnushogi 30 +will generate one move every 30 seconds, while +.B gnushogi 5:00 +will generate one move every 5 minutes. + +If two or more arguments are given, they will be used to set tournament +time controls with the first argument of each pair being the number of moves and the second +being the total clock time in minutes[:seconds]. Thus, entering +.B gnushogi 60 5 +will set +the clocks for 5 minutes (300 seconds) for the first 60 moves, +and +.B gnushogi 30 3:30 +will allow 3 minutes and 30 seconds for 30 moves. + +.B gnushogi 30 5 1 :30 +will allow 5 minutes for the first 30 moves and 30 seconds for each move after that. +Up to 4 pairs of controls may be specified. + +If no argument is given the program will prompt the user for level of play. + +For use with +.B xshogi +, see the documentation on this programs. +.SH BOOK +.PP +The book +.I gnushogi.book +consists of a sequence of openings. +An opening begins with a line starting with a +.B ! +, the rest of the line is comments. +Following this is a series of moves in algebraic notation alternating black +and white separated by white space. A move may have a +.B ? +after it indicating this move should never be made in this position. +Moves are stored as position:move so transpositions between openings +can take place. +.SH HASHFILE +.PP +The hashfile if created should be on the order of 4 megabytes or +.B gnushogi -c 22. +This file contains positions and moves learned from previous games. +If a hashfile is used the computer makes use of the experience it +gained in past games. Tests run so far show that it plays no worse +with the hashfile than without, but it is not clear yet whether +it provides a real advantage. +.SH LEGAL MOVES +.PP +.B Note: +Piece letters are determined by the language file. +What is specified here is the default English. +.PP +Once +.I gnushogi +is invoked, the program will display the board and prompt the user +for a move. To enter a move, use the notation +.B 7g7f +where the first letter-number pair indicates the origination square +and the second letter-number pair indicates the destination square. +An alternative is to use the notation +.B p7f +where the first letter indicates the piece type (p,l,n,s,g,b,r,k). +To promote append a + the type of the new piece to the move, as in +.B 2d2c+ +or +.B P2c+. +.SH "FUNCTION LETTERS" +.TP +.B -L lang +Use language +.I lang from the file +.B gnushogi.lang. +If -L is not specified it uses the first language in the file. +.TP +.B -a +Do not search on opponents time. +.TP +.B a +Do search on opponents time. +.TP +.B -b bookfile +Use bookfile for opening book. +.TP +.B -B binbookfile +Use binbookfile for binary opening book. +.TP +.B -S size +Size of binbookfile for memory based books. For creating a binbookfile. +.TP +.B -P plylevels +Number of plys to include in the binbookfile. For generating a binbookfile. +.TP +.B -c size +Create a new HASHFILE. File size is 2^size entries of approximately 65+? bytes. +.TP +.B -h +Do not use hashfile. +.TP +.B h +Do use hashfile. +.TP +.B -l pathname +Pathname of the loadfile use with the +.BR get +or +.BR xget. +.TP +.B -r length +Rehash length times in searching entries for position in transposition table. +.TP +.B -s pathname +Pathname of the save file to use with the +.BR save +command. +.TP +.B -t +Show statistics for HASHFILE +.TP +.B -T size +Set the transposition table size to 2^size entries. +.TP +.B -v +Show version and patchlevel. +.TP +.B -x value +Use +.BR value +as the evaluation window +.BR xwndw. +.SH COMMANDS +.PP +In addition to legal moves, the following commands are available as responses. +.B Note: +command names are determined by the +.I language +file and may vary with the implementation. This is default English. +.PP +.B alg +-- allow algrbraic input (not implemented) +.PP +.B Awindow +-- change Alpha window (default score + 90) +.PP +.B Bwindow +-- change Beta window (default score - 90) +.PP +.B beep +-- causes the program to beep after each move. +.PP +.B bd +-- updates the current board position on the display. +.PP +.B book +-- turns off use of the opening library. +.PP +.B both +-- causes the computer to play both sides of a shogi game. +.PP +.B black +-- causes the computer to take the white pieces, if the computer is to move first the +.PP +.B bsave +-- saves a game to disk as a book textfile. +The program will prompt the user for a file name. +.PP +.B gamein +-- toggles game mode time control. Assumes the time specified for time control +is the time for a complete game. Input with the level command should be the game time +and the expected number of moves in a game. +.B go +command must be given. +.PP +.B coords +-- show coordinates on the display (visual only) +.PP +.B contempt +-- allows the value of +.I contempt +to be modified. +.PP +.B debug +-- asks for a piece as color piece, as wb or bn, and shows its calculated value on +each square. +.PP +.B debuglevel +-- sets level of debugging output if compiled with debug options. +.PP +.B depth +-- allows the user to change the +search depth of the program. The maximum depth is 29 ply. +Normally the depth is set to 29 and the computer terminates +its search based on elapsed time rather than depth. +If depth is set to (say) 4 ply, +the program will search until all moves +have been examined to a depth of 4 ply (with extensions up +to 11 additional ply for sequences of checks and captures). +If you set a maximum time per move and also use the depth command, +the search will stop at the specified time or the specified depth, whichever +comes first. +.PP +.B easy +-- toggles easy mode (thinking on opponents time) +on and off. The default is easy mode ON. If easy mode is disabled, +the keyboard is polled for input every so often and when input is +seen the search is terminated. It may also be terminated with a +.I sigint. +.PP +.B edit +-- allows the user to set up a board position. + +.B # +- command will clear the board. + +.B c +- toggle piece color. + +.B . +- command will exit setup mode. + +.B p3b +- place a pawn on 3b + +.B p3b+ +- place a promoted pawn on 3b + +.B p* +- place a pawn to the captured pieces + +Pieces are entered by typing a letter (p,l,n,s,g,b,r,k) for +the piece followed by the coordinate. + +The usual warning about the +.I language file +applies. +.PP +.B exit +-- exits gnushogi. +.PP +.B first +-- tells the computer to move first. Computer begins searching for a move. +(same as "go"). +.PP +.B force +-- allows the user to enter moves for both +sides. To get the program to play after a sequence of moves +has been entered use the 'black' or 'white' commands. +.PP +.B get +-- retrieves a game from disk. The program will +prompt the user for a file name. +.PP +.B hash +-- use/don't use hashfile. +.PP +.B hashdepth +-- allows the user to change the minimum depth for using the hashfile and the number of moves from the +begining of the game to use it. +.PP +.B help +-- displays a short description of the commands and the current status of options. +.PP +.B go +-- tells the computer to move first. Computer begins searching for a move. +(same as "first"). +.PP +.B hint +-- causes the program to supply the user with its predicted move. +.PP +.B level +-- allows the user to set time controls such as +60 moves in 5 minutes etc. In tournament mode, the program will +vary the time it takes for each +move depending on the situation. If easy mode is disabled (using +the 'easy' command), the program +will often respond with its move immediately, saving time on +its clock for use later on. +.PP +.B list +-- writes the game moves and some statistics +on search depth, nodes, and time to the file 'chess.lst'. +.PP +.B material +-- toggle material flag - draws on no pawns and both sides < rook +.PP +.B new +-- starts a new game. +.PP +.B p +-- evaluates the board and shows the point score for each piece. The total score for +a position is the sum of these individual piece scores. +.PP +.B post +-- causes the program to display the principle +variation and the score during the search. A score of +100 is equivalent to a 1 pawn advantage for the computer. +.PP +.B quit +-- exits the game. +.PP +.B random +-- causes the program to randomize its move +selection slightly. +.PP +.B rcptr +-- set recapture mode. +.PP +.B remove +-- backout the last level for both sides. Equal to 2 +.I undo's. +.PP +.B reverse +-- causes the board display to be reversed. That +is, the black pieces will now appear at the top of the board. +.PP +.B rv +-- reverse board display. +.PP +.B save +-- saves a game to disk. The program will prompt +the user for a file name. +.PP +.B switch +-- causes the program to switch places with +the opponent and begin searching. +.PP +.B test +-- performs some speed tests for MoveList and CaptureList generation, and ScorePosition position scoring +for the current board. +.PP +.B time +-- set computers time remaining, intended for synchronizing clocks among multiple players. +.PP +.B tsume +-- toggle tsume mode. In tsume mode, not all possible moves will be +generated. If a king is in check, only moves that makes the king not being +in check are generated. If the king is not in check, only moves that give +check to the opponents king are generated. +.PP +.B undo +-- undoes the last move whether it was the computer's +or the human's. You may also type "remove". This is equivalent +to two "undo's" (e.g. retract one move for each side). +.PP +.B white +-- causes the computer to take the black pieces, if the computer is to move first the +iB go +command must be given. +.PP +.B xget +-- read an +.Ixshogi +position file. +.PP +.B xsave +-- save as an +.Ixshogi +position file. +.PP +.B xwndw +-- change X window. The window around alpha/beta used to determine whether the position +should be scored or just estimated. +.SH BUGS +.PP +.fi +.SH SEE ALSO +.nf +xshogi(6) +.fi + diff --git a/doc/listserv.ref b/doc/listserv.ref new file mode 100644 index 0000000..2bd676e --- /dev/null +++ b/doc/listserv.ref @@ -0,0 +1,63 @@ +This is a message from Pieter Stouten, one of the owners of a listserver +for the game of Shogi. + + +------------------------------------------------------------------------------------------- + + +H O W T O D E A L W I T H T E C H N I O N +================================================= + +There is still some confusion about posting to SHOGI-L. Therefore this +explanation about how it all works. This file will also automatically +be sent to all new subscribers to the list. +One thing that must be clear is the fundamental difference between + + the List Server or + + + and + + the Shogi Discussion List or . + + +LISTSERV +-------- + +Basically, the List Server must be addressed in two cases: +1) when you want to register with a specific list or, after registering, + when you want to change or query your options related to this registration. +2) when you want to retrieve files from an archive maintained by this + List Server. +Addressing the List Server must be done using standard commands e.g. +1) "Subscribe a_nice_list first_name last_name" or + "Set a_nice_list repro" +2) "Get file_name file_type" +(without the quotes, of course). In order to find out which files are +available for retrieval, you must send the command "Index Shogi-L" to the +List Server. If you want to know your distribution options, you must send +the command "Query Shogi-L". To find out who else subscribes, you send +the command "Review Shogi-L". Everything must be sent to the List Server ! + + +SHOGI-L +------- + +The Shogi Discussion List is a redistribution list, which redistributes all +incoming mail to the subscribers to the list. This mail does not need special +headers or commands. The only restriction is that lines must not exceed 80 +characters. It is redistributed unmoderated and unchanged. +Everybody who subscribes to SHOGI-L is authorized to have his/her mail +redistributed. If you (as subscriber) suddenly get a message that you are not +authorized, please check whether you are working from the same node as the +one you registered from or whether the full path to your node is still the +same or if there are any known problems with gateways affecting you. In any +case, if you experience this problem, please check with your local network +personnel first, before bombarding us with requests and complaints. + +Having said this all, there should be no obstruction anymore and everybody +now can post all his/her Shogi information, requests and musings (?). + +Pieter Stouten +17-th September 1990. + diff --git a/doc/shogi.rules b/doc/shogi.rules new file mode 100644 index 0000000..f98231c --- /dev/null +++ b/doc/shogi.rules @@ -0,0 +1,117 @@ + + +These are the rules of Shogi, as distributed by the Shogi-l listserver. + + +------------------------------------------------------------------------------------------ + + +S H O G I R U L E S +==================== + + +Shogi is a Japanese board game played by two players. +The object of the game is to capture the opponent's King. +Shogi is played on a nine-by-nine board. The vertical rows are called files, +the horizontal ones ranks or just rows. Each player has twenty pieces: +one King, two Gold Generals, two Silver Generals, two kNights, +two Lances, one Rook, one Bishop and nine Pawns. +The player moving up the board and making the first move is referred to as +black and his opponent white, although in Shogi sets all pieces have the +same colour. They are differentiated only in direction: pieces pointing +away from a player are his. The pieces lie flat on the board and have +their Japanese name written on them. + + +THE MOVES +--------- + +King: one step in any direction per move +Gold General: one step per move any way except diagnoally backward + (as a king but not diagonally backward) +Silver General: one step per move forwards or diagonally + (as a king but not sideways or vertically backward) +Knight: one step to left or right, and two steps forward + (the only piece which may jump over other pieces) +Rook: moves vertically or horizontally any distance +Bishop: moves diagonally any distance +Lance: moves forward any distance +Pawn: one step forward + +Apart from the King and the Gold General all pieces can promote. +After promotion their moves are as follows: ++ Promoted Silver, promoted kNight, promoted Lance and promoted Pawn all + move as a Gold. ++ The promoted Rook in addition to the moves of the unpromoted Rook can + move one step in the diagonal directions. It either moves like a Rook + or like a King. ++ The promoted Bishop in addition to the moves of the unpromoted Bishop + can move one step horizontally or vertically. It either moves like a + Bishop or like a King. + + +PROMOTION +--------- + +The three rows furthest away from a player are called the promotion zone. Apart +from the King and the Gold, any piece can be promoted to a more powerful piece +when it makes a move completely or partly in the promotion zone. So, when a +piece moves into, out of or fully inside the promotion zone it may be promoted +upon completion of its move. Promotion is optional, provided that the piece +still can make a legal move in case it is not promoted: if a Pawn or a Lance +move to the last row, or a Knight moves to either of the last two rows, it must +be promoted. In Shogi sets promoting a piece is done by turning this piece +upside down. Its promoted name is written on its other side. + + +CAPTURING AND DROPPING PIECES +----------------------------- + +When one piece moves onto the same square as an opponent's piece, the +opponent's piece is captured. All pieces capture in the same way that they +move. Captured pieces become part of the capturer's force. In a later move, +instead of moving a piece on the board, a player may put a piece that he +has captured from his opponent back onto the board, in an empty square. +This is called dropping a piece. Pieces are always dropped unpromoted: if +a promoted piece is captured, it reverts to its unpromoted rank. +Pieces may be dropped on any empty square on the board with only three +restrictions: + 1) After dropping a piece it must be able to make a legal move. This applies + to Pawns, Knights or Lances. They may not be dropped onto a square from + which they will never be able to move. + 2) Attacking the King by dropping a Pawn on the square in front of him is not + allowed if the King cannot prevent being captured on the following move. + To use the Chess expression: checkmating the King with a Pawn drop is + prohibited. + 3) A pawn may only be dropped on a file (vertical row) if there is no other + unpromoted pawn of the same player on that file. + + +DRAWS +----- + +The game of Shogi has very few draws (roughly 1 percent), mainly because of +the possibility to drop pieces. Draws cannot be offered and can arise from +two situations: + 1) A position (including the pieces in hand) occurs 4 times with the same + player to move ("Sennichite"). However, if this is caused by consecutive + checks (direct attacks on the King, threatening to capture it on the next + move) by one side, the player giving these checks loses the game. + 2) Both players have moved their King into the the promotion zone (or they + cannot be prevented to do so) and the Kings cannot be checkmated. In + that case the players may decide to count their pieces where the King does + not count, the Rook and Bishop count as 5 points, and all other pieces as + one point. Promotion is disregarded. If both players have at least 24 + points the game is a draw ("Jishogi"). If a player has less, he loses the + game. + Of course, a player can refuse to count pieces when he still has mating + chances or chances to gain material which would affect the outcome of the + counting. There is no strict rule about what to do if this is not the case, + but nonetheless a player refuses to count up (e.g. because he does not have + enough points for a draw). It has been generally accepted that in such a + case the game ends and the pieces are counted after one player has managed + to get all his pieces protected in the promotion zone. + +Chris Sterritt and Pieter Stouten, 12-th June 1990. +Last revision 9-th October 1991 - Draws (Jishogi rule). + diff --git a/doc/tutorial1.gam b/doc/tutorial1.gam new file mode 100644 index 0000000..e77309e --- /dev/null +++ b/doc/tutorial1.gam @@ -0,0 +1,113 @@ +# Shogi Game 1 (amateur game, amateur comment): introductory game. +# +# Below you find (the English translation of) an annotated game which was +# published in the Dutch Shogi magazine "81" and in the Dutch beginners +# booklet. It has proven to be a very useful game to explain some basic +# principles of Shogi. Also, it is a rather straight forward game compared +# to professional games where in most cases very diffuse middle game fights +# take place. +# +# Pieter Stouten, 14-th May 1990. +# +# --------------------------------------------------------------------------- +# +# Black: Michael Trent (1-dan). White: David Murphy (2-dan). + 1.P2f P3d 2.P2e B3c +[ This move is necessary, otherwise white can exchange pawns: 3.P2d Px2d + 4.Rx2d. He would thus get a pawn in hand and open up his rook file. ] + 3.P7f P4d +[ White closes the bishop diagonal again. He plans to play ranging rook + (the rook goes to 5, 4, 3 of 2b; a defensive strategy) and in that case + he*d better avoid an exchange of bishops. One of the reasons is that he + will have problems developing his pieces without leaving holes for + bishop drops. ] + 4.S4h R3b 5.P3f S4b 6.K6h K6b +[ In general the rook play an important role in the attacks. It is wise + to move the king away from the area where the initial fights will be + and both players act according to the Shogi proverb "keep the rook and + king apart". ] + 7.K7h K7b 8.P5f P5d 9.G4i-5h G4a-5b +[ Both players use their second gold general to build their castle. ] + 10.S6h +[ In itself this move is not bad. However, it will become clear that + black plans a quick attack and in that case it is wiser to omit this + move. ] + 10... S5c 11.P1f P1d +[ The advance of the edge pawns must be timed very well. The remark at + blacks tenth move applies here too: this move is good if black wants to + play a slow game, because it eleminates a future B1e. ] + 12. P4f K8b 13.N3g S7b +[ Black develops his knight in order to start an attack over the second, + third and fourth files. White strengthens his kings position and awaits + the attack. He aims at a counter attack as soon as black has broken + through into the white camp. Probably white*s breakthrough will take + place later, but he has good compensation in the form of a stronger + castle. This theme occurs very often in static rook versus ranging rook + games. ] + 14.P4e R4b +[ Black starts his attack and white puts up a very passive defence. His + rook has a hard task now to penetrate the black position. Moreover, he + blocks his own bishop. It seems much better to start a counter attack + with 14... P3e, later to be followed by B2b, B5a or Bx4d in order to + use his rook more actively. ] + 15.Px4d Sx4d 16.P*4e S5c +[ 16... Sx4e is more active. A silver general is normally more valuable + than a knight, but white gets two pawns in hand and black none, while + the knight might come in handy for white too. ] + 17.Bx3c+ Nx3c 18.P2d Px2d +[ Black threatens to break through and white had to consider taking the + pawn on 2d or starting a counter attack with Nx4e. If he choses the + latter, black can play Px2c+ followed by +P3c. The disadvantage is the + black "tokin" (=promoted pawn) that white will get in his camp; the + advantage is that it will cost black two more moves to promote his + rook. Because white did not trust the result after engaging in a + "semeai" (=mutual attack) with 18... N4e would to give a positive + result, he captured the pawn on 2d. Making the right decision in + moments like this often makes the difference between a win and a loss: + miss one attacking chance and you will be forced to defend the whole + game until the unavoidable defeat; on the other hand, an unsound attack + can destroy all "aji" (=potential, meaning possibilities, threats) + without getting anything in return. ] + 19.Rx2d Nx4e 20.Nx4e Rx4e 21.R2a+ P*4g +[ Now it becomes clear why black*s 10.S6h was not good. Had this move + been omitted, then white would not have had the time to play 13... S7b + and after R2a+ the gold on 6a would hang. Thus black would have kept + "sente" (=initiative). Instead of 21... P*4g B*6d is a very good move, + because after 22.P*2h black does not have a pawn in hand anymore and he + is being threatened with the annoying 22... N*4f 23.G5g N3h+ 24.S4g + +N4h also. Black can also counter 21... B*6d with 22.N*3g. White would + then reply with 22... R4b 23.B*3c P*4g 24.Bx4b+ Sx4b. The white rook + has played its role and instead of spending moves on saving it white + starts to scatter black*s defences by successive pawn drops on the + fourth file: 25.Gx4g P*4f 26.G5g N*6e 27.G5h P4g+ 28.Gx4g P*4f. This + analysis was provided by Kato Hifumi, 9-dan professional (the highest + regular grade). Destroying the coherence of the enemy pieces (their + shape) by dropping pawns is one of the most important Shogi techniques. + With the actual move 21... P*4g white missed a good chance. ] + 22.Sx4g P*4f 23.B*3g Px4g+ 24.+Rx6a +Px3g +[ 23.B*3g seems pointless, but a closer look reveals that it is actually + quite mean. On move 24 white cannot capture blacks "Ryu" (=dragon + =promoted rook) with his silver: 24... Sx6a 25.N*7d K7b 26.G*8b mate. + By attacking the front of the white castle and threatening to mate him + there, black has the chance to break down the white defences from the + side. ] + 25.+Rx5b S*6b +[ Here 25... B*4d would be much better, because it is defensive and + attacking at the same time. After e.g. 26.G*4c Bx9i+ 27.Gx5c black + threatens 28.+Rx7b Kx7b 29.S*6a K8b 30.S*7a Kx7a 31.G*7b mate. White + is one move quicker, however. He has the following beautiful "tsume" + (mating sequence where every move is check): 27... N*8f 28.Px8f S*8g + 29.Kx8g B*9h 30.K7h Bx8i+ 31.K8g +b8i-8h 32.K9f L*9e mate. This + illustrates the sharpness of Shogi: one move can make the difference + between winning and losing. ] + 26.P*4f Rx4f +[ This move eliminates white*s last chances. 26... R4b 27.+Rx4b Sx4b + 28.R*4a seems annoying, but after 28... B*3c 29.S7g B*3b white wins + the rook and with his "tokin" on 3g there still is some hope. ] + 27.N*6e +P4g +[ White cannot defend anymore, so he starts a desparate attack. Black + does not lose the right track, however. ] + 28.Nx5c+ +Px5h 29.+Nx6b +Px6h 30.Gx6h N*8f 31.Px8f B*6i 32.Gx6i + R4h+ 33.N*6h +Rx6h 34.Gx6h S*8g 35.Kx8g N*9e 36.K7h Resigns +[ White resigns here, because after 36... B*8g 27.K7g his attack has + petered out. ] diff --git a/doc/tutorial2.gam b/doc/tutorial2.gam new file mode 100644 index 0000000..1953a6c --- /dev/null +++ b/doc/tutorial2.gam @@ -0,0 +1,125 @@ +1.P-7f +[ This opens the bishop's diagonal. ] +1.... P-8d +[ This prepares a path for the rook. It declares a + Static Rook opening for White.] +2.S-6h +[ As long as white has a closed bishop's diagonal, + S-6h can be played. Black has the option to play + Ranging Rook. In this case, the silver should be placed + at 6g after pushing the pawn. If Black wants to play + Static Rook, the bishop's diagonal can be blocked with + S-7g.] +2.... P-3d +[ Now, Black has something to decide. S-7g will lead to a + Static Rook opening. P-6f normally would be followed by a + Ranging Rook opening, although it is possible in Static Rook. + Blocking the diagonal with tha pawn would prevent a bishop + exchange opening. Bishop exchange openings are not easy for + beginners. Bx2b+ is also possible, but it would lead to the + bishop exchange opening with a free development move for White.] +3.P-6f S-6b +[ Protect 5c and keep possible developments to 7c and 6c. Another + possible move is S-7b aiming at S-8c and further development towards + the weak head of Black's bishop.] +4.S-6g +[ This would be very unusual for Static Rook openings. Therefore, it + Black will most probably move into a Ranging Rook opening. The Gold + Fortress is the castle, which is usually used in Static Rook vs. + Static Rook openings, but S-6g would lead to the Silver Fortress + if Black will play Static Rook. Nevertheless, White cannot be shure + about Black's plans...] +4.... P-5d +[ This is possible when playing against Rainging Rook or against Static + Rook.] +5.P-9f +[ The time when, when an edge pawn should or can be pushed, is critical. + Pushing the edge pawn of a castle is more critical than pushing the + edge pawn of the attackers side. + ] +5.... G6a-5b +[ The edge pawn is not pushed, because in Ranging Rook openings, attacks will + be on files supported by the rook. It is very difficult to attack on the + edge. Therefore, White doesn't fear P-9e, because this would give White an + extra tempo. + Normally, G6a-5b is the first move for building a Boat castle, the typical + castle of the Static Rook side when playing against Ranging Rook. + Even if Black decides to play Static Rook, it is still possible to move + into the Gold Fortress. G6a-5b strengthen White's castle side. White keeps + the bishop's diagonal open, because this keeps the threat of exchaning + bishops in case Black plans to play Ranging Rook (which is most probably the + case). Exchanging bishops is better for the Static Rook side when playing + agaainst Ranging Rook. G4a-3b would declare to create a Fortess castle, which + normally played in Static Rook vs. Static Rook games.] +6.R-5h +[ Now, a center file Ranging Rook is declared.] +6.... K-4b +[ White moves into the Boat castle. It would still be possible to build + A Fortress.] +7.K-4h +[ Now, Black definitely plays a Ranging Rook openings. It would make no sense + to keep a Static Rook option for Black in mind. Most likely, Black will move + into a Mino castle. The edge pawn has not been pushed to 1f, therefore also + the Bear-in-the-hole castle is possible.] +7.... K-3b +8.K-3h P-1d +[ White's Boat Castle is complete. Black still moves into the Mino Castle. + Pushing an edge pawn is often answered by pushing the opposing edge pawn.] +9.P-1f +[ In the Bear-in-the-Hole Castle, the edge pawn would normally not be pushed. + Therefore, Black will adopt some version of the Mino Castle after building + the basic pattern.] +9.... P-9d +[ Preparing own attack possibilities. L-9c, R-9b would lead to an edge attack, + which would be difficult for Black to defend. In this case, Black would aim + at a counterattack. This moves prevents P9f-9e, an attack move of Black. + Preventing attack moves normally lead to slow games.] +10.K-2h +[ Moving into the Mono Castle.] +10.... S-4b +[ Typical development against Ranging Rook. Now, S6b-5c or S4b-5c is possible. + Normally, the Static Rook side waits some moves until the attack formation + is decided. There is some time, because Black's first order castle is not + created, yet.] +11.S-3h +[ This completes the so-called Incomplete Mino Castle. The other Gold should be + on 5h to create a Complete Mino. The best and most used castles use three + generals to defend the king.] +11.... P-8e +[ Increase preassure to the bishop's head. Black has to be aware of P8e-8f. + Exchanging the pawns would be good for White, because it would open the + Rook file for White. Furthermore, it would be impossible to defend the square + 8g if White now could exchange the pawns...] +12.B-7g +[ This is the only defense. If Black would play Static Rook, also a silver could + defend on 7g, but in Ranging Rook openings, the bishop almost always is placed + on 7g against a pawn advanced to 8e.] +12.... S-3c +[ Decision towards a specific attack formation for White. This move aimes at + Black's castle.] +13.P-4f +[ Towards a second stage castle which is stronger at its head.] +13.... P-3e +[ Vanguard pawn opening. The Vanguard pawn must be supported, i.e. S-3d is + recommended.] +14.S-4g +[ Strengthen the castle at the head. There is some need to protect the silver + and to protect the kings side, i.e. G-3h is very recommended.] +14.... S-3d +15.P-5f +[ This is another move towards a slow game. Black does not want to go into + a skirmish at the center file.] +15.... S-5c +[ Support attack of White either towards Black's king or supporting the White + rook pawn. Normally, the Vanguard pawn will further be strengthen.] +16.R-8h +[ It is common in Ranging Rook openings to switch the rook from file to file, + testing the opponent's response. Opposing rooks is the most aggressive version.] +16.... P-4d +[ This signals the start of the middle-game. The pawn will advance to 4e, which will + lead to the first exchange.] +17.G-3h +[ It's time to strengthen the castle, because the middle-game will soon start.] +17.... P-4e + + diff --git a/misc/gnushogi.lng b/misc/gnushogi.lng new file mode 100644 index 0000000..8eb45f1 --- /dev/null +++ b/misc/gnushogi.lng @@ -0,0 +1,234 @@ +/* 001:eng: */ " plnsgbrplnsbrk ", +/* 002:eng: */ " PLNSGBRPLNSBRK ", +/* 003:eng: */ "987654321", +/* 004:eng: */ "ihgfedcba", +/* 005:eng: */ "moves", +/* 006:eng: */ "", +/* 007:eng: */ "", +/* 008:eng: */ "", +/* 009:eng: */ "bBwW", +/* 010:eng: */ " score depth nodes time ", +/* 011:eng: */ " score depth nodes time\n", +/* 012:eng: */ " ", +/* 013:eng: */ " ", +/* 014:eng: */ " %s\n", +/* 015:eng: */ " 9 8 7 6 5 4 3 2 1", +/* 016:eng: */ " 1 2 3 4 5 6 7 8 9", +/* 017:eng: */ " -", +/* 018:eng: */ " 1. 40 moves in 5 minutes", +/* 019:eng: */ " 2. 40 moves in 15 minutes", +/* 020:eng: */ " 3. 40 moves in 30 minutes", +/* 021:eng: */ " 4. all moves in 15 minutes", +/* 022:eng: */ " 5. all moves in 30 minutes", +/* 023:eng: */ " 6. all moves in 15 minutes, 30 seconds fischer clock", +/* 024:eng: */ " 7. all moves in 30 minutes, 30 seconds fischer clock", +/* 025:eng: */ " 8. 1 move in 1 minute", +/* 026:eng: */ " 9. 1 move in 15 minutes", +/* 027:eng: */ "10. 1 move in 30 minutes", +/* 028:eng: */ "# Clear board\n", +/* 029:eng: */ ". Exit to main\n", +/* 030:eng: */ "gnushogi.tbk", +/* 031:eng: */ "Abort? ", +/* 032:eng: */ "Ambiguous Move %s!", +/* 033:eng: */ "Awindow", +/* 034:eng: */ "BAwindow= ", +/* 035:eng: */ "BBwindow= ", +/* 036:eng: */ "Beep: %-12s Transposition file: %s\n", +/* 037:eng: */ "White %s Black %s %d %s\n", +/* 038:eng: */ "Bwindow: ", +/* 039:eng: */ "Bwindow", +/* 040:eng: */ "GNU Shogi %sp%s command summary\n", +/* 041:eng: */ "GNU Shogi %sp%s", +/* 042:eng: */ "Castled Black %s White %s\n", +/* 043:eng: */ "", +/* 044:eng: */ "Computer mates!", +/* 045:eng: */ "Comp: mate in %d!", +/* 046:eng: */ "Computer: %-12s Opponent: %s\n", +/* 047:eng: */ "Computer: %s", +/* 048:eng: */ "Could not open file", +/* 049:eng: */ "Counting transposition file entries, wait!\n", +/* 050:eng: */ "Create failed for %s\n", +/* 051:eng: */ "Depth: %-12d Response time: %d sec\n", +/* 052:eng: */ "Depth: %d", +/* 053:eng: */ "Depth= %d%c ", +/* 054:eng: */ "Draw %s\n", +/* 055:eng: */ "DrawPiece: color[sq] err", +/* 056:eng: */ "Drawn game! %s", +/* 057:eng: */ "Drawn game!\n", +/* 058:eng: */ "Drawn game!", +/* 059:eng: */ "Easy mode: %s", +/* 060:eng: */ "Editing: %s", +/* 061:eng: */ "Enter #moves #minutes: ", +/* 062:eng: */ "Enter Level: ", +/* 063:eng: */ "Enter file name: ", +/* 064:eng: */ "Enter piece & location: ", +/* 065:eng: */ "Enter piece: ", +/* 066:eng: */ "Filling transposition file, wait!\n", +/* 067:eng: */ "GNU Shogi display (MS-DOS, Mar 90)", +/* 068:eng: */ "GNU Shogi display (Nov 89)", +/* 069:eng: */ "GNU Shogi %s (pl %s)", +/* 070:eng: */ "Game saved", +/* 071:eng: */ "Hin/Hout/Tcol/Coll/Fin/Fout = %ld/%ld/%ld/%ld/%ld/%ld\n", +/* 072:eng: */ "Hint: %s\n", +/* 073:eng: */ "Hit to return: ", +/* 074:eng: */ "Human ", +/* 075:eng: */ "Illegal(no match)%s\n", +/* 076:eng: */ "Illegal(no match)%s", +/* 077:eng: */ "Illegal(in check)%s", +/* 078:eng: */ "Illegal move\n", +/* 079:eng: */ "Level: %ld", +/* 080:eng: */ "Max Moves", +/* 081:eng: */ "Max Tree= %5d", +/* 082:eng: */ "MoveLimit= ", +/* 083:eng: */ "My move is: %5s\n", +/* 084:eng: */ "My move is: %5s", +/* 085:eng: */ "Testing Eval Speed", +/* 086:eng: */ "S6h move silver to 6h beep turn %s\n", +/* 087:eng: */ "No moves", +/* 088:eng: */ "No pieces", +/* 089:eng: */ "Gen %ld Node %ld Tree %d Eval %ld Rate %ld EC %d/%d RS hi %ld lo %ld \n", +/* 090:eng: */ "Nodes= %8ld, Nodes/Sec= %5ld", +/* 091:eng: */ "Nodes= %ld Nodes/sec= %ld\n", +/* 092:eng: */ "OFF", +/* 093:eng: */ "ON", +/* 094:eng: */ "Operator time(hundredths)= ", +/* 095:eng: */ "Opponent mates!", +/* 096:eng: */ "Opp: mate in %d!", +/* 097:eng: */ "Opponent: %s", +/* 098:eng: */ "Playing without hashfile", +/* 099:eng: */ "Random: %-12s Easy mode: %s\n", +/* 100:eng: */ "Random: %s", +/* 101:eng: */ "Repetition", +/* 102:eng: */ "Gnushogi version %s patchlevel %s\n", +/* 103:eng: */ "S%d m%d ps%d gt%c m%d ps%d gt%c", +/* 104:eng: */ "Score= %d", +/* 105:eng: */ "Score", +/* 106:eng: */ "Setup successful\n", +/* 107:eng: */ "Testing CaptureList Speed", +/* 108:eng: */ "Testing MoveList Speed", +/* 109:eng: */ "The file contains %d entries out of max %d\n", +/* 110:eng: */ "Time Control %s %d moves %d sec %d add %d depth\n", +/* 111:eng: */ "TimeControl %d Operator Time %d\n", +/* 112:eng: */ "Transposition table: %s", +/* 113:eng: */ "Usage: Gnushogi [-a] [-t] [-c size] [-s savefile][-l listfile] [-x xwndw]\n", +/* 114:eng: */ "WAwindow= ", +/* 115:eng: */ "WBwindow= ", +/* 116:eng: */ "Black %d:%02d White %d:%02d\n", +/* 117:eng: */ "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n", +/* 118:eng: */ "Black", +/* 119:eng: */ "White", +/* 120:eng: */ "Wwindow: ", +/* 121:eng: */ "Your move is? ", +/* 122:eng: */ "\n ", +/* 123:eng: */ "\nMove# %d Target= %ld Clock: %ld\n", +/* 124:eng: */ "\nYour move is? ", +/* 125:eng: */ "\n\n", +/* 126:eng: */ " move score depth nodes time flags capture\n", +/* 127:eng: */ "\n", +/* 128:eng: */ "2d2c+ move to 2c and promote material turn %s\n", +/* 129:eng: */ "alg", +/* 130:eng: */ "bd redraw board reverse board display\n", +/* 131:eng: */ "bd", +/* 132:eng: */ "beep", +/* 133:eng: */ "white", +/* 134:eng: */ "book", +/* 135:eng: */ "both", +/* 136:eng: */ "c Change sides\n", +/* 137:eng: */ "shogi.000", +/* 138:eng: */ "shogi.lst.%d", +/* 139:eng: */ "computer mates!\n", +/* 140:eng: */ "computer will soon mate!\n", +/* 141:eng: */ "computer", +/* 142:eng: */ "contempt= ", +/* 143:eng: */ "contempt", +/* 144:eng: */ "coords show coords rv reverse video\n", +/* 145:eng: */ "coords", +/* 146:eng: */ "debuglevel= ", +/* 147:eng: */ "debuglevel", +/* 148:eng: */ "debug", +/* 149:eng: */ "depth set search depth clock set time control\n", +/* 150:eng: */ "depth= ", +/* 151:eng: */ "depth", +/* 152:eng: */ "easy", +/* 153:eng: */ "edit edit board force toggle manual move mode\n", +/* 154:eng: */ "edit", +/* 155:eng: */ "enter piece & location: \n", +/* 156:eng: */ "first", +/* 157:eng: */ "force", +/* 158:eng: */ "7g7f move from 7g to 7f quit Exit Shogi\n", +/* 159:eng: */ "game file= ", +/* 160:eng: */ "get", +/* 161:eng: */ "gnushogi %sp%s game\n", +/* 162:eng: */ "go", +/* 163:eng: */ "hashdepth= ", +/* 164:eng: */ "hashdepth", +/* 165:eng: */ "hash", +/* 166:eng: */ "help", +/* 167:eng: */ "hint suggest a move post turn %s principle variation\n", +/* 168:eng: */ "hint", +/* 169:eng: */ "level", +/* 170:eng: */ "list game to shogi.lst book turn %s used %d of %d\n", +/* 171:eng: */ "list", +/* 172:eng: */ "new", +/* 173:eng: */ "P*5e drop pawn to 5e easy turn %s\n", +/* 174:eng: */ "tsume toggle tsume mode hash turn %s\n", +/* 175:eng: */ "opponent mates!\n", +/* 176:eng: */ "opponent will soon mate!\n", +/* 177:eng: */ "post principle variation hint suggest a move\n", +/* 178:eng: */ "post", +/* 179:eng: */ "p", +/* 180:eng: */ "quit", +/* 181:eng: */ "random randomize play new start new game\n", +/* 182:eng: */ "random", +/* 183:eng: */ "rcptr", +/* 184:eng: */ "remove", +/* 185:eng: */ "reverse", +/* 186:eng: */ "rv", +/* 187:eng: */ "r", +/* 188:eng: */ "save game to file get game from file\n", +/* 189:eng: */ "save", +/* 190:eng: */ "setup", +/* 191:eng: */ "set", +/* 192:eng: */ "shade toggle shade white stars toggle stars\n", +/* 193:eng: */ "stars", +/* 194:eng: */ "switch sides with computer both computer match\n", +/* 195:eng: */ "switch", +/* 196:eng: */ "test", +/* 197:eng: */ "time", +/* 198:eng: */ "try ", +/* 199:eng: */ "ttable collision detected", +/* 200:eng: */ "undo undo last ply remove take back a move\n", +/* 201:eng: */ "undo", +/* 202:eng: */ "black computer plays black white computer plays white\n", +/* 203:eng: */ "black", +/* 204:eng: */ "w", +/* 205:eng: */ "xshogi.position.read", +/* 206:eng: */ "xshogi", +/* 207:eng: */ "xget", +/* 208:eng: */ "xwndw= ", +/* 209:eng: */ "xwndw", +/* 210:eng: */ "yes", +/* 211:eng: */ "Illegal move in book %d %s %s", +/* 212:eng: */ "Can't find book.", +/* 213:eng: */ "Book used %d(%d).", +/* 214:eng: */ "true", +/* 215:eng: */ "false", +/* 216:eng: */ "exit", +/* 217:eng: */ "clock", +/* 218:eng: */ "Computer", +/* 219:eng: */ "Open failure for file: %s", +/* 220:eng: */ "Time Control Error", +/* 221:eng: */ "material", +/* 222:eng: */ "time %d %d\n", +/* 223:eng: */ "I have no idea\n", +/* 224:eng: */ "Not Enough Material", +/* 225:eng: */ "Illegal position", +/* 226:eng: */ "beep", +/* 227:eng: */ "gamein", +/* 228:eng: */ "otime", +/* 229:eng: */ "hard", +/* 230:eng: */ "tsume", +/* 231:eng: */ "Tsume: %s", +/* 232:eng: */ "Tsume: %-12s Force: %s\n", +/* 233:eng: */ "", +/* 234:eng: */ "", diff --git a/misc/gnushogi.pat b/misc/gnushogi.pat new file mode 100644 index 0000000..bcd5a5d --- /dev/null +++ b/misc/gnushogi.pat @@ -0,0 +1,167 @@ +CASTLE_S_S +# Fortress +[0] 5 p7f p8g b8h s6h g6i | P8d P3c +[1] 6 p8g p7f s8h b7g | P8e P3d +[2] 8 p8g p7f s7g p6g p5g g7h k6h g5h +[3] 5 b8h p8g p7f s7g g7h k6i +[4] 5 k5i g6i g6g s7h b8h p8g p7f p6f +[5] 8 k6i b7i g7h s7g p8g p7f +[6] 7 k6i s8h g7h g5h p8g b7g p7f p6f p5f +[7] 8 k6i g7h b6h g5h p8g s7g p7f p6f p5f +[8] 9 10 k7i g7h p8g p7f s7g p6f p5f g6g +[9] 11 k8h g7h p9f p8g p7f p6f s7g g6g | P9d +[10] k7i g8h p9g p8g s7g g6g p7f p6f | P9e +[11] l9i n8i k8h g7h s7g p8g p9f p7f +[12] 13 b7g | S7b +[13] 6 b7g s8h g7h | S8d +# without pawns +[14] 2 s7g g7h k6h g5h +[15] 8 k7i g7h g6g +[16] 7 k6i g7h b6h g5h s7g +[17] 11 l9i n8i k8h g7h s7g +[18] 6 k6i s8h g7h g5h p8g b7g +ATTACK_S_S +[0] 1 2 p5g p4g p3g p2f p1g r2h s3i +[1] 3 p5g p4g p3g p2f s4h r2h n2i +[2] 4 s3h p4g p3g p2f r2h +[3] 5 6 7 s4h p4g p3f p2f p1g r2h n2i +[4] 12 14 15 17 p3f p2e s2f p1f r2h n2i l1i +[5] 12 n2i r2h s3g p3f p2e p1e | P1d +[6] 9 11 l1i r2h s4g n3g p4f p3f p2f p1e | P1c +[7] 8 s4h p5f p4g n3g p3f p2f r2h l1g +[8] s4h p5f p4g n3g p3f p2f r1h l1g +[9] 10 s4g p4f n3g n3f r2h l1g p1e +[10] s4g p4f n3g n3f r1h l1g p1e +[11] s5f p5g p4f p3f n3g r2h p2e p1f l1i +[12] 13 n2i s3g p3f p2e l1g r2h +[13] n2i s3g p3f p2e l1g r1h +[14] 16 n2i l1i r2h p2e p3f s3e +[15] 16 n2i l1i r2h p2e p3e s2f +[16] s3e p2d r2h +[17] s1e p2d r2h +CASTLE_S_R +[0] 1 2 g6i g5h k5i b8h p7f s7i n8i l9i +[1] 3 p9f l9i n8i b8h k7h g6i g5h p8g p7f p6g p5f +[2] 4 l9i n8i s7i g6i g5h k6h b8h p8g p6g p7f +[3] 7 8 l9i n8i g6i b8h k7h s6h g5h p9f p8g p7f p6g p5f +[4] 5 l9i n8i s7i g6i g5h k7h b8h p8g p6g p7f p5g +[5] 6 l9h k8h n8i s7i g6i b7g p9g p8g p7f +[6] k9i l9h s8h g7h g7i p8g b7g p7f p6g +[7] l9i n8i k8h g7h p9f p8g b7g g6g p7f p6f +[8] 9 l9i n8i b8h k7h g6i g5h s7g p7e p6g s5g p5f | P7c +[9] l9i n8i k8h g7h b7g g6g s5g s7f p6f p5f p8e p7e +# without pawns +[10] 1 l9i n8i b8h k7h g6i g5h +[11] 3 l9i n8i g6i b8h k7h s6h g5h +[12] 2 l9i n8i s7i g6i g5h k6h b8h +ATTACK_S_R +[0] 1 2 6 r2h p2e +[1] 2 3 5 6 13 s4h r2h n2i l1i p5f p3f +[2] 13 l1i s4h r2h n3g p4f p3f +# Center-file Vanguard Pawn +[3] 4 l1i n2i r2h s6h p3g p4g s5g p5e | P5c P4d +[4] l1i n2i r2h s6h p3g p4g s5f p5e | P5c +# King's Head Vanguard Pawn +[5] l1i b8h s7g s5g p7e | P7c +# rushing silver +[6] 7 p2e p1f r2h s3h +[2] 8 10 p2e p3f p1f s2f r2h +[8] 9 p3e p2e p1f s2f r2h +[9] s3e p2e p1f r2h +[10] p2e s1e p1f r2h +# edge attack +[11] 12 l1g r2h +[12] l1g r1h p1d +# slow +[13] 11 s4g n3g r2h l1i p4f p3f +CASTLE_R_S +# going into Mino or Bear-in-the-Hole +[0] 1 g6i g4i s3i n2i l1i k4h p4g p3g p2g p1g +[1] 2 4 g6i g4i s3i n2i l1i k2h p4g p3g p2g p1g +# Bear-in-the-Hole +[2] 3 g4i s3i n2i k1i g5h l1h p4g p3g p2g p1g +[3] 12 g3i n2i k1i g3h s2h l1h p4g p3g p2g p1g +# Incomplete Mino +[4] 5 8 g4i n2i l1i s3h k2h p3g p2g p1f +# Complete Mino +[5] 6 9 g4i n2i l1i g5h s3h k2h p4g p3g p2g p1f +# High Mino +[6] 7 10 g4i n2i l1i s3h k2h g4g p2g p4f p3f p1f +# Silver Crown +[7] 11 n2i l1i g3h k2h g4g s2g p4f p3f p2f p1f +# Incomplete Mino without pawns +[8] 5 g4i n2i l1i s3h k2h p3g p2g p1f +# Complete Mino without pawns +[9] 6 g4i n2i l1i g5h s3h k2h p4g p3g p2g p1f +# High Mino without pawns +[10] 7 g4i n2i l1i s3h k2h g4g +# Silver Crown without pawns +[11] n2i l1i g3h k2h g4g s2g +# Bear-in-the-Hole without pawns +[12] g3i n2i k1i g3h s2h l1h +CASTLE_R_R +[0] 1 l1i s3i g4i g6i k3h p2g p3g p4g +[1] 2 l1i g4i s2h k3h g5h p2g p3g p4g +[2] s2h k3h g4h g5h p2g p3g p4g +# without pawns +[3] 0 l1i s3i g4i g6i k3h +[4] 1 l1i g4i s2h k3h g5h +[5] 2 s2h k3h g4h g5h +CASTLE_S_U +[0] p1g p2e p3g p4g p5g p6g p7f p8g p9g n8i s7i g6i k5i g4i s3i n2i +[1] p8g p7f p6g g6i g5h p5f +ATTACK_S_U +[0] 1 2 p2f r2h +[1] 3 p2f s4h +[2] 6 p2f s3h +[3] 4 5 p2f s4h p3f +[4] p2f p4f p3f s4g n3g +[5] p2e p3f s3g p1e +[6] 7 p2e s2g p3g +[7] p2e s2f p1f p3f +CASTLE_R_U +[0] 4 r5h k5i g4i s3i +[1] 4 r6h k5i g4i s3i +[2] 4 r7h k5i g4i s3i +[3] 4 r8h k5i g4i s3i +[4] k3h g4i s3i +ATTACK_R_U +[0] 1 2 3 4 p7f p6f b7g +[1] r8h p7f p6f b7g s6g +[2] r7h p7f p6f b7g +[3] r6h p7f p6f b7g s6g +[4] r5h p7f p6f b7g s6g +CASTLE_U_U +[0] 1 p3g p4g p6g p7f n8i s7i g6i k5i g4i s3i n2i +[1] 2 3 p3g p4g p6f p7f b8h s7i g6i k5i g4i s3i +[2] 4 p6f p7f s7h b8h +[3] 4 p6f p7f s6h b8h +[4] p6f p7f s6h b8h p1e +ATTACK_U_U +[0] p7f +ATTACK_R_* +# going into Ranging Rook +[0] 1 5 8 10 b7g p7f p6f k5i g4i s3i p2g +# 2nd file Ranging Rook +[1] 2 r8h b7g p7f p6f k5i g4i s3i +[2] 3 4 r8h n8i g6i b7g s6g p7f p6f +[3] r8h n8i g7h b7g s6g p7f p6f +[4] r8h n8i g5h b7g s6g p7f p6f +# 3rd file Ranging Rook +[5] 6 7 r7h b7g p7f p6f k5i g4i s3i +[6] r7h s6g g5h p8g b7g p7f p6f +[7] r7h s6g p8g b7g p7f p6f p5f +# 4th file Ranging Rook +[8] 9 r6h b7g s6g p7f p6f k5i g4i s3i +[9] r6h n8i g6i p8g b7g s6g p7f p6f +# 5th file Ranging Rook +[10] 11 13 r5h p8g b7g s6g k5i g4i s3i +[11] 12 r5h n8i g7h p8g b7g s6g p7f p6f +[12] r5i n8i p8g b7g s6g s4g p7f p6f +[13] r5h n8i p8g b7g s6g g4g p7f p6f +CASTLE_U_* +[0] 1 p3g p4g p6g p7f n8i s7i g6i k5i g4i s3i n2i +[1] 2 3 p3g p4g p6f p7f b8h s7i g6i k5i g4i s3i +[2] 4 p6f p7f s7h b8h +[3] 4 p6f p7f s6h b8h +[4] p6f p7f s6h b8h p1e diff --git a/misc/gnushogi.tbk b/misc/gnushogi.tbk new file mode 100644 index 0000000..dedb7ad --- /dev/null +++ b/misc/gnushogi.tbk @@ -0,0 +1,3170 @@ +# BASIC LINES +# +# --------------------------- +# Static Rook vs. Static Rook +# --------------------------- +# +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +P5f K4a K6i G5b G5h S3c P3f P4d B7i B3a P6f P7d +# +P7f P8d P2f P8e B7g P3d S8h G3b G7h S4b B2b+ G2b +S7g S7b S3h S8c P2e S3c P3f S8d S3g S9e B*5f B*7b +# +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +P5f K4a K6i G5b G5h S3c B7i B3a P6f P4d P1f P1d +# +P7f P3d P2f G3b P2e B8h+ S8h S2b S7g K4b S4h S3c +G7h S6b K6h P9d P9f P6d P4f S6c S4g S5d S5f K3a +# +P7f P8d P2f P8e P2e G3b B7g P3d S8h B7g+ S7g S2b +S3h S6b G7h S3c S2g P7d S2f S7c S1e B*5d G5h S6d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b +P9f P1d P1f P3d R3f G3c K4h P6d B9g S6c P7f K4a +# +P7f P8d S7h P8e S7g P3d P2f S4b P2e S3c G7h G3b +K6i S6b G5h K4a P5f P5d B7i G5b S3h P4d S2g 5b4c +# +P7f P8d S7h P8e S7g P3d P2f S4b P2e S3c G7h G3b +K6i S6b G5h K4a P5f P5d B7i G5b S3h P4d S2g 5b4c +# +P7f P8d P5f P8e B7g P5d R5h S6b S6h P3d K4h K4b +K3h K3b P1f P1d K2h 6a5b S3h P9d P9f 2b7g+ S7g S4b +# +P7f P8d S6h P3d P6f S6b S6g P5d P9f 6a5b R5h K4b +K4h K3b K3h P1d P1f P9d K2h S4b S3h P8e B7g S3c +# +P7f P3d P2f P4d P2e B3c S4h S3b P5f P5d 4i5h 6a5b +S7h G4c B7i K4b P2d P2d B2d B2d R2d P*2c R2h K3a +# +P7f P3d P2f P5d P5f S6b S4h P8d P2e G3b G7h P8e +P2d P2d R2d P*2c R2h P8f P8f R8f P*8g R8b K6i K4a +# +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +P5f K4a K6i G5b P3f P7d G5h S3c B7i B3a P6f P4d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2h P8f +P8f R8f P*8g R8d S3h S6b S2g P3d S3f B3c P7f S2b +# +P2f P8d P2e P8e G7h G3b S4h S6b P2d P2d R2d P*2c +R2f P3d P7f P8f P8f R8f P*8g R8d P4f P6d S4g S6c +# +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f +P8f R8f R3d B8h+ S8h P*2h S2h B*4e R2d P*2c B*7g R8h+ +# +P7f P8d S7h P3d S7g S6b S4h S4b P2f S3c G7h G3b +G5h G5b P5f P5d P3f P7d B7i B3a K6i K4a P6f P4d +# +P7f P8d S7h P3d S7g S6b S4h S4b P2f S3c G7h G3b +G5h G5b P5f P5d P3f P7d B7i B3a K6i K4a P6f P4d +# +# ---------------------------- +# Static Rook vs. Ranging Rook +# ---------------------------- +# +# Static vs. 2nd-file +# +P7f P3d P2f P4d P2e B3c S4h S3b P5f P5d 4i5h S4c +K6h R2b K7h K6b P3f K7b P9f P9d S6h K8b P4f S7b +# +P2f P3d P7f P4d P2e B3c S4h R2b K6h S4b K7h K6b +4i5h K7b P5f K8b P3f S7b S6h S4c 6h5g G3b P4f P2d +# +# Static vs. 3rd-file +# +P7f P3d P2f P4d S4h R3b P2e B3c K6h S4b K7h K6b +4i5h K7b P5f 4a5b P3f K8b P9f P9d P1f P1d P4f S7b +# +P7f P3d P2f P4d S4h R3b K6h P3e K7h K6b P4f 4a5b +P2e R3d S4g K7b S6h K8b P9f S7b G3h P1d G2g S4b +# +P7f P3d P9f P4d P2f R3b P2e B3c S4h S4b K6h K6b +K7h K7b P5f K8b P3f P5d 4i5h 4a5b P1f P1d S6h S4c +# +# Static vs. 4th-file +# +P7f P3d S4h P4d P4f S4b S4g S4c P3f R4b R4h B3c +P1f P1d P2f K6b K6h K7b K7h S6b 4i5h P5d P5f S5c +# +P7f P3d S4h P4d P4f S4b S4g S4c P3f R4b R4h B3c +P1f P1d P2f K6b K6h K7b K7h S6b 4i5h P5d P5f S5c +# +P7f P3d P2f P4d P5f S3b S4h R4b K6h K6b 4i5h K7b +K7h K8b S6h S7b P9f P9d 4h5g S4c P7e 4a5b S7g P5d +# +P7f P3d P2f P4d P5f S3b S4h R4b K6h K6b 4i5h K7b +K7h K8b S6h S7b P9f P9d P3f 4a5b 6h5g S4c P2e B3c +# +P7f P3d P2f P4d P5f S3b S4h R4b K6h K6b 4i5h K7b +K7h K8b S6h S7b P9f P9d P3f 4a5b 6h5g S4c P2e B3c +# +# Static vs. 5th-file +# +P7f P8d S6h P3d P6f S6b S6g P5d P9f 6a5b R5h K4b +K4h K3b K3h P1d P1f P9d K2h S4b S3h P8e B7g S3c +# +P7f P8d P5f P5d S6h P3d P6f S6b R5h K4b K4h K3b +K3h 6a5b S6g P1d P1f S4b K2h P7d B7g P8e G7h 4b5c +# +# ---------------------------- +# Ranging Rook vs. Static Rook +# ---------------------------- +# +# 3rd-file vs. Static +# +P7f P3d P6f P8d R7h P8e B7g S6b S6h P5d K4h K4b +K3h K3b K2h P1d P1f P9d P9f 6a5b S3h P7d 6i5h S4b +# +# 5th-file vs. Static +# +P7f P8d P5f P8e B7g P5d S6h P3d P6f S6b R5h K4b +K4h K3b K3h 6a5b K2h P1d P1f S5c S3h B3c P4f P4d +# +P7f P3d P2f P4d S4h S4b P5f R5b K6h K6b K7h K7b +4i5h K8b P9f P9d P6f S4c G6g S5d S5g S7b B7g P6d +# +# ----------------------------- +# Ranging Rook vs. Ranging Rook +# ----------------------------- +# +P7f P3d P6f P3e S7h R3b S6g K6b B7g K7b R8h P1d +P1f 4a5b P8f P2d P8e R3d S2h P2e K4h S4b 6i5h S8b +# +# ADDITIONAL LINES +# +# Source: SHOGI May 1984 Issue No. 49 +# +# p.2 +1.P-7f P-3d 2.P-6f P-8d 3.S-7h S-6b 4.P-5f P-5d 5.P-2f S-4b +6.S-4h G-3b 7.S-7g K-4a 8.G-7h G-5b 9.K-6i S-3c 10.G-5h P-7d +11.P-3f B-3a 12.B-7i P-4d 13.P-2e G5b-4c 14.B-4f B-6d 15.S-3g K-3a +16.K-7i K-2b 17.B-5g P-8e 18.K-8h P-9d 19.G5h-6g S-7c 20.P-1f S-8d +# p.4 Double Fortress +1.P-7f P-3d 2.P-6f S-6b 3.S-7h P-6d 4.P-2f S-3b 5.P-2e S-3c +6.S-6g S-6c 7.S-4h P-8d 8.P-5f P-8e 9.B-7g B-3a 10.G-7h P-5d +11.S-5g G-3b 12.K-6i K-4a 13.G-5h G-5b 14.K-7i P-4d 15.P-3f B-4b +16.B-5i P-7d 17.K-8h N-7c 18.P-1f P-1d 19.P-9f P-9d 20.R-3h G5b-4c +# p.13 Game 1 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.G-7h P-5d +6.P-5f G6a-5b 7.K-6i P-4d 8.G-5h G-4c 9.P-3f S-3c 10.B-7i B-3a +11.P-6f K-4b 12.P-3e Px3e 13.Bx3e P-4e 14.S-3g S-4d 15.B-6h K-3b +16.P-2f B-6d 17.R-3h N-3c 18.P-6e B-5c 19.P-1f G4a-4b 20.P-1e P*3e +# p.13 Game 2 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.P-2f S-4b 5.S-4h G-3b +6.G-7h K-4a 7.P-5f P-5d 8.K-6i G-5b 9.P-3f P-7d 10.G-5h S-3c +11.B-7i B-3a 12.P-6f P-4d 13.P-1f G5b-4c 14.P-1e B-6d 15.N-3g K-3a +16.B-4f S-7c 17.K-7i P-8e 18.K-8h K-2b 19.S-5g Bx4f 20.Px4f S-6d +# p.13 Game 3 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.G-7h G-3b +6.K-6i P-5d 7.P-5f K-4a 8.G-5h G-5b 9.P-6f S6b-5c 10.P-2f P-5e +11.Px5e Bx5e 12.P-2e S-5d 13.P-2d Px2d 14.Rx2d P*2c 15.R-2h P-6d +16.S-5g B-2b 17.G5h-6g S-5c 18.S-4f S-4d 19.P-7e G-6c 20.S-7f P-8e +# p.13 Game 4 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.P-2f S-4b 5.S-4h G-3b +6.G-7h K-4a 7.P-5f P-5d 8.K-6i G-5b 9.P-3f P-7d 10.G-5h S-3c +11.B-7i B-3a 12.P-6f P-4d 13.P-1f G5b-4c 14.P-1e P-9d 15.G5h-6g P-9e +16.B-6h S-7c 17.K-7i S-6d 18.P-2e N-7c 19.P-4f R-7b 20.S-8f N-8e +# p.13 Game 5 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.G-7h G-3b +6.K-6i P-5d 7.P-5f K-4a 8.G-5h G-5b 9.P-3f S-3c 10.P-6f B-3a +11.B-7i P-4d 12.P-1f P-7d 13.P-1e B-6d 14.S-3g P-8e 15.G5h-6g B-7c +16.L-1g S-5c 17.R-1h G-2b 18.B-6h R-6b 19.K-7i P-6d 20.K-8h B-8d +# p.13 Game 6 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.P-2f S-4b 5.S-4h G-3b +6.G-7h K-4a 7.P-5f P-5d 8.K-6i G-5b 9.P-3f S-3c 10.G-5h B-3a +11.B-7i P-7d 12.P-6f P-4d 13.G5h-6g G5b-4c 14.B-6h P-8e 15.K-7i B-6d +16.N-3g K-3a 17.K-8h K-2b 18.R-3h P-9d 19.P-1f P-1d 20.S-5g B-7c +# p.14 Double Ranging Rook +1.P-7f P-3d 2.P-6f P-3e 3.S-7h R-3b 4.S-6g K-6b 5.B-7g K-7b +6.R-8h P-3f 7.Px3f Rx3f 8.P*3g R-3d 9.G-4h G-6b 10.K-4i S-3b +11.K-3h P-1d 12.P-1f P-2d 13.P-9f P-9d 14.G6i-5h G4a-5b 15.P-8f P-2e +16.P-8e S-2c 17.P-6e N-3c 18.B-6f S-8b 19.N-7g S-2d 20.S-5f S-3e +# +# Source: SHOGI November 1986 Issue No. 64 +# +# p.4 +1.P-7f P-3d 2.P-2f P-4d 3.P-2e B-3c 4.S-4h S-3b 5.P-5f P-5d +6.P-3f R-4b 7.K-6h K-6b 8.K-7h K-7b 9.G4i-5h S-6b 10.P-9f P-9d +11.N-3g P-4e 12.S-5g S-5c 13.P-1f P-1d 14.R-2f G-6b 15.P-2d Px2d +16.P-3e Bx8h+ 17.Sx8h S-4d 18.Rx2d P*2c 19.R-2f Sx3e 20.R-2i B*3h +# p.9 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.P-2f S-4b 5.S-4h G-3b +6.G-7h K-4a 7.K-6i P-5d 8.P-5f G-5b 9.G-5h S-3c 10.P-6f P-4d +11.B-7i B-3a 12.P-3f P-7d 13.G5h-6g G5b-4c 14.S-3g P-8e 15.P-2e B-6d +16.B-4f S-7c 17.K-7i K-3a 18.K-8h K-2b 19.P-1f P-9d 20.P-9f P-1d +# p.16 +1.P-7f P-3d 2.P-2f P-4d 3.S-4h S-3b 4.P-5f R-4b 5.K-6h K-6b +6.K-7h S-7b 7.S-5g G4a-5b 8.B-7g K-7a 9.K-8h S-4c 10.L-9h S-5d +11.P-6f K-8b 12.K-9i P-6d 13.S-8h P-7d 14.G-7i G-6c 15.G-5h N-7c +16.P-2e B-3c 17.P-3f P-4e 18.G5h-6h P-9d 19.G6h-7h P-9e 20.B-5i P-8d +# p.17 Game 4 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.P-2f S-4b 5.S-4h G-3b +6.G-7h K-4a 7.K-6i P-5d 8.P-5f G-5b 9.P-3f P-4d 10.G-5h G5b-4c +11.P-6f S-3c 12.B-7i B-3a 13.G5h-6g P-7d 14.S-3g B-6d 15.B-6h K-3a +16.K-7i K-2b 17.K-8h P-8e 18.P-1f S-7c 19.S-4f P-7e 20.Px7e P-4e +# p.17 Game 1 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-5f P-5d +6.G-7h G6a-5b 7.K-6i P-4d 8.P-3f G-4c 9.G-5h S-3c 10.P-6f B-3a +11.B-7i P-8e 12.S-3g G-3b 13.P-3e Px3e 14.Bx3e B-6d 15.P-6e B-4b +16.G5h-6g S-5c 17.K-7i K-4a 18.K-8h P-6d 19.Px6d Sx6d 20.S-3f P-5e +# p.17 Game 2 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2f S-6b 7.P-9f P-1d 8.S-3h P-6d 9.P-7f P-3d 10.P-7e S-6c +11.K-4h K-4a 12.K-3i P-4d 13.S-6h S-4b 14.R-7f K-3a 15.P-6f B-3c +16.S-6g G-7b 17.B-9g K-2b 18.N-7g P-4e 19.K-2h R-8d 20.S-5h P-9d +# p.17. Game 3 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2f S-6b 7.P-1f P-3d 8.S-3h P-6d 9.P-7f P-8f 10.Px8f Rx8f +11.P*8g R-8b 12.P-1e S-6c 13.P-3f S-5d 14.N-3g G-5b 15.P*2d Px2d +16.Rx2d P*2c 17.Rx3d Bx8h+ 18.Sx8h G-3c 19.R-3e B*2d 20.P*2b Sx2b +# +# Source: SHOGI, March 1987, Issue No.66, p.17 +# +# p.4 +# Static v. Fourth +P7f P3d P2f P4d P2e B3c S4h S3b P5f P5d 4i5h R4b +K6h K6b K7h K7b P3f S6b P9f P9d P5e P5e B5e S4c +# p.4 +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h K4a +P5f P5d K6i G5b P3f P4d G5h S3c B7i B3a P6f P7d +# p.7 (game 1) +P7f P3d P2f P4d S4h S4b K6h S6b 4i5h P7d P6f G3b +K7h R7b G6g P7e P7e R7e P*7f R7a P5f K4a S6h P6d +# p.7 (game 2) +P7f P8d R7h P8e B7g P3d P6f S6b S6h K4b K4h K3b +K3h 6a5b K2h P5d L1h B3c P5f K2b S5g S5c P3f L1b +# p.7 (game 3) +P7f P3d P2f P4d S4h R3b P2e B3c K6h S4b K7h K6b +P5f K7b P3f K8b 4i5h P5d P4f 4a5b N3g R2b S6h S7b +# p.7 (game 4) +P2f P8d P2e P8e G7h G3b P2d P2d R2d P1d R2f P3d +P9f N3c S6h P*2e R5f S4b P3f S6b P7f G2c P7e K4a +# p.7 (game 5) +P7f P3d P2f P4d S4h S4b K6h P5d K7h R5b P5f K6b +4i5h K7b P3f K8b P2e B3c P4f G3b S5g L9b R3h G4c +# p.7 (game 6) +P7f P8d P5f P8e B7g P5d R8h P3d S6h S6b P6f P6d +K4h K4b K3h K3b K2h 6a5b L1h S5c K1i B3c S5g P4d S2h K2b +# p.17 (game 1) +P7f P8d S6h P3d S7g S6b P2f S4b S4h P5d P5f G3b +G7h K4a K6i G5b G5h S3c B7i B3a P6f P4d P3f P7d +5h6g 5b4c B6h P9d K7i P9e S3g S5c P2e B4b K8h B5a +S2f B7c B4f P6d +# p.17 (game 2) +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b P5f K4a +G7h P5d K6i G5b P3f S3c G5h B3a B7i P4d P6f P7d +# p.17 (game 3) +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +K6i K4a P5f P7d G5h G5b P3f S3c B7i B3a P6f P4d +# p.17 (game 4) +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h K4a +K6i P5d P5f G5b G5h S3c P3f P4d P6f B3a B7i P7d +# p.17 (game 5) +P2f P3d P7f P4d P2e B3c S4h S4b P5f S4c G4i5h R2b +P4f K6b P3f K7b K6h P4e 8h3c+ N3c B*8h G3b S5g R2a +# p.17 (game 6) +P7f P8d P5f P8e B7g P5d R5h K4b S6h P3d K4h S6b +P5e P5e R5e K3b R5i S4b G7h P6d K3h P4d S5g S4c +# +# Source: SHOGI May 1987 Issue No. 67 +# +# p.4 +1.P-7f P-3d 2.P-2f P-4d 3.P-2e B-3c 4.S-4h S-3b 5.P-5f P-5d +6.G4i-5h P-8d 7.S-7h P-8e 8.B-7g G6a-5b 9.B-6h K-4b 10.S-7g G-4c +11.P-2d Px2d 12.Bx2d P*2c 13.Bx3c+ Kx3c 14.K-6h K-2b 15.P-6f S-6b +16.G-6g S-5c 17.S-5g P-7d 18.K-7h P-4e 19.P-4f Px4f 20.Sx4f P*4d +# p.15 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-5f P-5d +6.G4i-5h G-3b 7.G-7h K-4a 8.K-6i G-5b 9.B-7i P-4d 10.P-3f G5b-4c +11.S-3g S-3c 12.P-6f B-3a 13.G5h-6g S-5c 14.B-6h B-4b 15.K-7i K-3a +16.K-8h P-7d 17.P-3e Px3e 18.Bx3e P-4e 19.R-4h S5c-4d 20.B-6h S-3d +# p.16 Game 2 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2f S-6b 7.P-1f P-1d 8.S-3h P-6d 9.P-7f P-8f 10.Px8f Rx8f +11.P*8g R-8b 12.P-3f P-3d 13.N-3g G-5b 14.P*2d Px2d 15.Rx2d K-4b +16.Rx3d G-2c 17.Rx6d Bx8h+ 18.Sx8h B*2h 19.P*2d G-1c 20.B*4e P*6c +# p.16 Game 3 +1.P-7f P-8d 2.S-6h P-3d 3.B-7g P-8e 4.S-4h S-6b 5.P-4f P-5d +6.S-4g S-5c 7.S-5f G-3b 8.G-7h P-7d 9.P-2f K-4a 10.P-2e P-7e +11.Px7e S-6d 12.S-4e P-5e 13.Sx3d P-5f 14.Px5f Bx7g+ 15.Sx7g B*5g +16.P-2d Px2d 17.B*6f Bx6f+ 18.Sx6f B*4g 19.Rx2d P*2b 20.B*2e Bx2e+ +# p.16 Game 4 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h P-5d 5.P-5f G6a-5b +6.G-7h S-3b 7.K-6i P-4d 8.G-5h G-4c 9.P-6f P-7d 10.B-7i B-3a +11.P-3f P-8e 12.G5h-6g B-6d 13.S-3g B-7c 14.B-6h K-4b 15.K-7i K-3a +16.K-8h S-5c 17.P-1f P-6d 18.R-3h R-6b 19.P-1e P-6e 20.Px6e Rx6e +# p.16 Game 5 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-5f P-5d +6.G4i-5h G-3b 7.P-6f K-4a 8.G-6g G-5b 9.B-7i P-4d 10.P-3f G5b-4c +11.K-6h S-3c 12.K-7h B-3a 13.S-3g S-5c 14.K-8h B-4b 15.G-7h K-3a +16.P-2f P-7d 17.P-2e K-2b 18.P-1f B-5a 19.P-1e B-7c 20.L-1g P-8e +# p.16 Game 6 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2f S-6b 7.P-1f P-1d 8.S-3h P-6d 9.P-7f P-3d 10.R-3f G-3c +11.B-7g P-4d 12.P-4f P-5d 13.S-6h S-5c 14.S-4g S-3b 15.R-2f S-4c +16.K-6i G-3b 17.G-5h G-5b 18.P-3f K-6b 19.P-5f G-6c 20.N-3g N-3c +# p.17 Game 3 +1.P-2f P-3d 2.P-7f P-4d 3.P-2e B-3c 4.S-4h S-4b 5.P-5f S-4c +6.G4i-5h P-3e 7.K-6h R-4b 8.K-7h K-6b 9.S-5g K-7b 10.S7i-6h K-8b +11.P-9f S-7b 12.P-9e G4a-5b 13.P-5e P-4e 14.S-5f S-4d 15.S-5g P-6d +16.R-4h P-5d 17.Px5d G-6c 18.P-4f Gx5d 19.Px4e Sx4e 20.Sx4e Gx4e +# p.17 Game 1 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.P-2f S-4b 5.S-4h G-3b +6.G-7h K-4a 7.K-6i P-5d 8.P-5f G-5b 9.G-5h P-7d 10.P-6f S-3c +11.B-7i B-3a 12.P-3f P-4d 13.B-4f N-7c 14.G5h-6g G5b-4c 15.P-2e B-4b +16.K-7i K-3a 17.K-8h R-7b 18.S-3g S-5c 19.S-2f P-4e 20.B-6h S5c-4d +# p.17 Game 2 +1.P-7f P-8d 2.P-2f P-8e 3.B-7g P-3d 4.S-8h G-3b 5.G-7h Bx7g+ +6.Sx7g S-4b 7.S-3h S-3c 8.P-3f S-7b 9.P-4f P-6d 10.S-4g S-6c +11.G-5h G-5b 12.K-6h K-4b 13.K-7i K-3a 14.S-5f P-7d 15.N-3g N-7c +16.P-6f G5b-4b 17.P-2e R-8a 18.K-8h R-6a 19.P-1f P-1d 20.P-9f P-9d +# p.17 Game 3 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.G-7h G-3b +6.K-6i K-4a 7.P-5f P-5d 8.G-5h G-5b 9.P-6f P-4d 10.B-7i S-3c +11.P-3f B-3a 12.S-3g G5b-4c 13.G5h-6g P-8e 14.P-3e Px3e 15.Bx3e P-4e +16.B-6h S-5c 17.K-7i S5c-4d 18.K-8h B-6d 19.P*3f P-7d 20.R-4h K-3a +# p.17 Game 4 +1.P-7f P-8d 2.P-2f P-8e 3.B-7g P-3d 4.S-8h G-3b 5.G-7h Bx7g+ +6.Sx7g S-4b 7.S-3h S-3c 8.P-3f S-7b 9.P-4f P-6d 10.S-4g S-6c +11.G-5h G-5b 12.K-6h K-4b 13.K-7i P-7d 14.S-5f S-5d 15.N-3g K-3a +16.P-6f P-9d 17.P-9f P-1d 18.P-1f K-2b 19.K-8h N-7c 20.P-4e R-6b +# +# Source: SHOGI July 1987 Issue No.68 +# +# p.2 Game 5 +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c +R2f S6b S3h P6d P1f S6c P4f P3d S4g P1d +S5f S5d P7f P8f P8f R8f P*8g R8b G4h G5b +P3f P4d P9f P9d P3e 5b4c P3d G3d R3f P*3e +# p.2 Game 6 +P7f P8d S6h P3d S7g S6b S4h S4b P5f P5d +G7h G3b K6i K4a G5h P7d P6f P8e 5h6g G5b +B7i P6d P3f 4b5c B4f N7c S5g R8a K7i G6c +P3e P3e B3e P6e R3h P6f 5g6f P*6e S5g G4b +# p.16 Game 1 +P7f P8d S6h P3d S7g S6b S4h S4b P5f P5d +4i5h G3b P6f K4a G6g G5b P3f P4d B7i S3c +K6h B3a K7h 5b4c K8h B4b G7h K3a S3g S5c +P2f K2b P2e P7d P1f B5a P1e B7c L1g P8e +# p.16 Game 2 +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c +R2f S6b P1f P1d S3h P3d P7f P8f P8f R8f +P*8g R8b P4f P6d S4g S6c S5f S5d G4h G5b +S4e B8h+ S8h S4e P4e N3c N7g K4b P7e P2d +# p.16 Game 3 +P7f P8d S6h P3d S7g S6b S4h S4b P5f P5d +4i5h G3b P6f K4a G6g G5b P3f P4d B7i 5b4c +K6h S3c K7h B3a S3g S5c K8h B4b G7h K3a +P2f K2b P2e P7d P1f B5a P1e B7c L1g P8e +# p.16 Game 4 +P7f P8d S6h P3d S7g S6b S4h P5d P5f S4b +G7h 6a5b K6i G3b G5h K4a P6f P7d P3f P5e +S5g 6b5c P2f S5d P4f P5f S5f P6d P2e G6c +7h6g N7c K7h S5c P2d P2d R2d P*2c R2e S4d +# p.16 Game 5 +P2f P3d P7f P4d P2e B3c S4h S4b K6h S4c +K7h R5b P4f K6b S6h K7b P5f K8b 4i5h S7b +P3f S5d 4h5g R4b N3g 4a5b P5e S6e P7e P5d +P6f S7f P5d G4c P7d S8e P9f G5d B9g P6d +# +# Source: SHOGI Sept.1987 Issue No.69 +# +# p.2 Game 1 +P7f P8d S6h P3d S7g S6b S4h P5d P5f G3b +G7h K4a K6i G5b G5h B3c P2f S2b P2e B5a +P3f S5c P4f P7d N3g P4d S6f P8e P5e P8f +P8f R8f P*8g R8d P4e P4e S6e P7e P2d P2d +# p.2 Game 2 +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c +R2f S6b S3h P3d P1f P1d P7f P8f P8f R8f +P*8g R8d P4f P6d S4g S6c S5f K4b K6h G5b +G4h S5d P3f P9d P9f P7d N3g P6e G4g G6b +# p.2 Game 3 +P7f P8d S6h P3d S7g S6b S4h S4b G7h G3b +K6i K4a P5f P5d G5h G5b P6f S3c B7i B3a +P3f P4d S3g 5b4c 5h6g P8e B6h P7d K7i S7c +B4f B4b K8h K3a P1f K2b P2f P9d P2e P7e +# p.4 Bishop exchange +P7f P3d P2f P4d P2e B3c S4h S3b P5f P5d +4i5h 6a5b S7h G4c B7i K4b S7g K3a P2d P2d +B2d B2d R2d P*2c R2h K2b K6h P8d K7h P9d +P9f P7d P6f S6b G6g S7c S5g P8e 6i6h S8d +# p.14 +P7f P3d P2f P4d S4h S4b P5f P5d K6h R5b +K7h K6b 4i5h K7b P9f K8b S5g L9b B7g K9a +K8h S8b S7h S5c P6f P4e P2e B3c G6g S4d +P8f P6d P8e G7a S8g P5e P5e R4b P5d G5b +# p.16 +P7f P8d S7h P3d P6f S6b R6h P5d K4h K4b +K3h K3b 6i5h 6a5b K2h P7d S3h S4b P4f P8e +B7g 4b5c P5f P1d P1f +# p.17 50th Kisey Title Match - Game 1 - 16th June 1987 +P7f P3d P2f P4d S4h S4b P5f S4c G4i5h R4b +K6h K6b K7h S7b P9f P9d S5g P6d S7i6h K7a +P5e G4a5b S5f P3e P2e B3c P6f R3b P6e Px6e +Sx6e B4b R2f #rd S6g N3c B7i P4e P7e P*6d +# p.17 50th Kisey Title Match - Game 2 - 30th June 1987 +P7f P8d S6h P3d P6f S6b R5h K4b K4h K3b +K3h G6a5b S6g P5d K2h S4b S3h P7d P4f P6d +P5f P8e B7g P6e P5e Px5e Px6e P8f Px8f N7c +G7h G6c S6f G5d G6g Nx6e B5i S6c N7g S6d +# p.17 50th Kisey Title Match - Game 3 - 7th July 1987 +P2f P3d P7f P4d S4h S3b P5f R4b K6h K6b +K7h K7b G4i5h K8b S6h S4c P3f S7b S6h5g P6d +P2e B3c P3e G3b Px3d Sx3d R3h G4c P1f P*3e +B5e P6e G6i6h R3b P4f P9d S4g P9e P*3f P5d +# p.17 9th Ladies' Osho Title Match - Game 1 - 11th March 1987 +P7f P3d P2f P4d S4h S3b P5f S4c G4i5h P3e +P2e B3c K6h R3b P1f K6b K7h S7b P9f K7a +S5g G4a5b P8f K8b K8g P5d S7h B4b R2f P1d +S4f P8d B7g P9d K8h S8c P6f G7b G6g G5b6b +# p.17 9th Ladies' Osho Title Match - Game 2 - +P7f P8d P5f P5d R5h S6b P5e Px5e Bx5e K4b +B7g K3b S6h P3d P6f G6a5b S6g S5c K4h P8e +K3h P1d K2h P1e S3h S3a4b S5f P4d P6e S4c +P4f P*5d P3f G4a4b N3g N3c R6h B1c S3h4g P3e +# p.17 28th Oi Title Match - Game 1 - 16th & 17th July 1987 +P2f P8d P2e P8e G7h G3b P2d Px2d Rx2d P*2c +R2f S7b P1f P1d S3h P3d P7f P8f Px8f Rx8f +P*2d Px2d Rx2d Rx7f Bx2b+ Sx2b B*7g B*1c R2h P7d +P4f N3c S4g N7c G5h R7e B6f R6e N7g R6d +# +# +# Source: Shogi World Vol. 1 No. 1 +# +# p.11 +# Third v. Static +P7f P3d P6f P8d R7h P8e B7g S6b S6h P5d K4h K4b +K3h K3b K2h P1d P1f P9d P9f 6a5b S3h P7d 6i5h S4b +# p.13 +# Central v. Static +P7f P8d P5f P8e B7g P5d S6h P3d P6f S6b R5h K4b +K4h K3b K3h 6a5b K2h P1d P1f S5c S3h B3c P4f P4d +# +# Source: Shogi World Vol. 1 No. 2 +# +# p.7 +# Static v. Static +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +P5f K4a K6i G5b G5h S3c P3f P4d B7i B3a P6f P7d +# p.12 +# Static v. Static +P7f P8d P2f P8e B7g P3d S8h G3b G7h S4b B2b+ G2b +S7g S7b S3h S8c P2e S3c P3f S8d S3g S9e B*5f B*7b +# +# Source: Shogi for beginners +# +# p.32 +# Static v. Centre-file +P7f P8d S6h P3d P6f S6b S6g P5d P9f 6a5b +R5h K4b K4h K3b K3h P1d P1f P9d K2h S4b +S3h P8e B7g S3c +# p.74 +# Static v. Third-file +P7f P3d P2f P4d S4h R3b P2e B3c K6h S4b +K7h K6b 4i5h K7b P5f 4a5b P3f K8b P9f P9d +P1f P1d P4f S7b N3g R2b P5e S4c +# p.81 +# Static v. Static +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +P5f K4a K6i G5b G5h S3c B7i B3a P6f P4d P1f P1d +P3f P7d P2e P8e S3g B6d +# p.146 +# Static v. Fourth-file +P7f P3d S4h P4d P4f S4b S4g S4c P3f R4b R4h B3c +P1f P1d P2f K6b K6h K7b K7h S6b 4i5h P5d P5f S5c +# p.147 +# Centre Game, Bishops off +P7f P3d P2f G3b P2e B8h+ S8h S2b S7g K4b S4h S3c +G7h S6b K6h P9d P9f P6d P4f S6c S4g S5d S5f K3a +# p.149 +# Right-side King +P7f P3d P2f P4d S4h S3b P5f S4c S6h P5d P3f B3c +6h5g R2b P4f K6b S4g K7b N3g S6b P8f R3b K4h B4b +# p.150 +# Static v. Opposing +P7f P3d P2f P4d P2e B3c S4h S3b P5f P5d 4i5h S4c +K6h R2b K7h K6b P3f K7b P9f P9d S6h K8b P4f S7b +# p.150 +# Static v. Third-File +P7f P3d P2f P4d S4h R3b K6h P3e K7h K6b P4f 4a5b +P2e R3d S4g K7b S6h K8b P9f S7b G3h P1d G2g S4b +# p.151 +# Static v. Opposing +P2f P3d P7f P4d P2e B3c S4h R2b K6h S4b K7h K6b +4i5h K7b P5f K8b P3f S7b S6h S4c 6h5g G3b P4f P2d +# p.152 +# Static v. Third-file +P7f P3d P9f P4d P2f R3b P2e B3c S4h S4b K6h K6b +K7h K7b P5f K8b P3f P5d 4i5h 4a5b P1f P1d S6h S4c +# p.152 +# Double Ranging +P7f P3d P6f P3e S7h R3b S6g K6b B7g K7b R8h P1d +P1f 4a5b P8f P2d P8e R3d S2h P2e K4h S4b 6i5h S8b +# p.153 +P7f P3d P2f P4d S4h S4b P5f R5b K6h K6b K7h K7b +4i5h K8b P9f P9d P6f S4c G6g S5d S5g S7b B7g P6d +# p.154 +# Bishop Exchange +P7f P8d P2f P8e P2e G3b B7g P3d S8h B7g+ S7g S2b +S3h S6b G7h S3c S2g P7d S2f S7c S1e B*5d G5h S6d +# p.155 +# Rook-On-Pawn +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b +P9f P1d P1f P3d R3f G3c K4h P6d B9g S6c P7f K4a +# +# Source: How to play shogi +# +# p.12 +P7f P8d S7h P8e S7g P3d P2f S4b P2e S3c G7h G3b +K6i S6b G5h K4a P5f P5d B7i G5b S3h P4d S2g 5b4c +S2f P1d P1f P7d P1e P1e S1e L1e L1e P*1c P*1b +S7c R1h S6d 1b1a+ B1a +# p.13 +P7f P8d P5f P8e B7g P5d R5h S6b S6h P3d +K4h K4b K3h K3b P1f P1d K2h 6a5b S3h P9d +P9f 2b7g+ S7g S4b P5e P5e R5e 6b5c R5i P*5d +G7h P7d S6f P8f P8f R8f N7g R8b P*8e P6d +# p.14 +P7f P8d S6h P3d P6f S6b S6g P5d P9f 6a5b +R5h K4b K4h K3b K3h P1d P1f P9d K2h S4b +S3h P8e B7g S3c P4f P3e S4g S3d P5f S5c +R8h P4d G3h P4e P4e S4e P*4f S3d G5h P6d +# p.22 +# Stativ v. Fourth-file +P7f P3d S4h P4d P4f S4b S4g S4c P3f R4b R4h B3c +P1f P1d P2f K6b K6h K7b K7h S6b 4i5h P5d P5f S5c +# p.22 +# Static v. Static +P7f P3d P2f P4d P2e B3c S4h S3b P5f P5d 4i5h 6a5b +S7h G4c B7i K4b P2d P2d B2d B2d R2d P*2c R2h K3a +# p.23 +# Centre Game +P7f P3d P2f P5d P5f S6b S4h P8d P2e G3b G7h P8e +P2d P2d R2d P*2c R2h P8f P8f R8f P*8g R8b K6i K4a +# p.23 +# Double Fortress +P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d +P5f K4a K6i G5b P3f P7d G5h S3c B7i B3a P6f P4d +# p.23 +# Central v. Static +P7f P8d P5f P5d S6h P3d P6f S6b R5h K4b K4h K3b +K3h 6a5b S6g P1d P1f S4b K2h P7d B7g P8e G7h 4b5c +# +# Source: Guide to Shogi Openings +# +# Primitive Climbing Silver 1 +1.P-2f P-8d 2.P-2e P-8e 3.P-2d? Px2d 4.Rx2d P-8f 5.P*2c? Px8g+ +# Primitive Climbing Silver 2 +1.P-2f P-8d 2.P-2e P-8e 3.P-2d? Px2d 4.Rx2d P-8f 5.Px8f P*8g +6.P*2c Px8h+ 7.Sx8h B*3e 8.R-2h Bx5g+ 9.Px2b+ Rx2b 10.Rx2b+? +# Primitive Climbing Silver 3 +1.P-2f P-8d 2.P-2e P-8e 3.P-2d? Px2d 4.Rx2d P-8f 5.Px8f P*8g +6.P*2c Px8h+ 7.Sx8h B*3e 8.R-2h Bx5g+ 9.Px2b+ Rx2b 10.P*2c R-1b +11.B*2b? G-3b? 12.Bx3a+ Gx3a 13.S*2b +# Primitive Climbing Silver 4 +1.P-2f P-8d 2.P-2e P-8e 3.P-2d? Px2d 4.Rx2d P-8f 5.Px8f P*8g +6.P*2c Px8h+ 7.Sx8h B*3e 8.R-2h Bx5g+ 9.Px2b+ Rx2b 10.P*2c R-1b +11.B*2b? P*2d 12.B-1a+ Rx1a 13.L*2g B*4e 14.Lx2d P*2g +# Primitive Climbing Silver 5 +1.P-2f P-8d 2.P-2e P-8e 3.P-2d? Px2d 4.Rx2d P-8f 5.Px8f P*8g +6.P*2c Px8h+ 7.Sx8h B*3e 8.R-2e Bx5g+ 9.R-5e +Bx6g 10.Rx5c+ P*5b +# Primitive Climbing Silver 6 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2h P-8f 7.Px8f Rx8f 8.P*8g R-8d 9.S-3h S-6b 10.S-2g G-5b? +11.S-3f K-4a 12.S-3e P-3d 13.P*2d Px2d 14.Sx2d B-4d 15.P-7f +# Primitive Climbing Silver 7 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2h P-8f 7.Px8f Rx8f 8.P*8g R-8d 9.S-3h S-6b 10.S-2g P-3d +11.S-3f B-3c 12.S-2e? P-3e +# Primitive Climbing Silver 8 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2h P-8f 7.Px8f Rx8f 8.P*8g R-8d 9.S-3h S-6b 10.S-2g P-3d +11.S-3f B-3c 12.P-7f S-2b 13.Bx3c+ Sx3c? 14.S-8h P-6d 15.S-2e +# Primitive Climbing Silver 9 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.P-2d Px2d 5.Rx2d P*2c +6.R-2h P-8f 7.Px8f Rx8f 8.P*8g R-8d 9.S-3h S-6b 10.S-2g P-3d +11.S-3f B-3c 12.P-7f S-2b 13.Bx3c+ Nx3c 14.S-8h G-5b 15.P-4f +# +# Wing Attack, Reclining Silver 1 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.S-4h S-6b 5.P-2d Px2d +6.Rx2d P*2c 7.R-2f P-3d 8.P-7f P-8f 9.Px8f Rx8f 10.P*8g R-8d +11.P-4f P-6d 12.S-4g S-6c 13.S-5f S-7d? 14.S-4e S-6e +# Wing Attack, Reclining Silver 2 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.S-4h S-6b 5.P-2d Px2d +6.Rx2d P*2c 7.R-2f P-3d 8.P-7f P-8f 9.Px8f Rx8f 10.P*8g R-8d +11.P-4f P-6d 12.S-4g S-6c 13.S-5f S-5d 14.K-6i? S-6e 15.Sx6e Bx8h+ +16.Sx8h B*4g +# Wing Attack, Reclining Silver 3 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.S-4h S-6b 5.P-2d Px2d +6.Rx2d P*2c 7.R-2f P-3d 8.P-7f P-8f 9.Px8f Rx8f 10.P*8g R-8d +11.P-4f P-6d 12.S-4g S-6c 13.S-5f S-5d 14.K-6h P-7d? 15.Bx2b+ Sx2b +16.B*9e P*8c 17.R-2h +# Wing Attack, Reclining Silver 4 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.S-4h S-6b 5.P-2d Px2d +6.Rx2d P*2c 7.R-2f P-3d 8.P-7f P-8f 9.Px8f Rx8f 10.P*8g R-8d +11.P-4f P-6d 12.S-4g S-6c 13.S-5f S-5d 14.K-6h K-4b 15.P-1f P-1d +16.P-9f P-9d 17.G-4h G-5b 18.P-3f P-7d 19.N-3g +# Wing Attack, Reclining Silver 5 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.S-4h S-6b 5.P-2d Px2d +6.Rx2d P*2c 7.R-2f P-3d 8.P-7f P-8f 9.Px8f Rx8f 10.P*8g R-8d +11.P-4f P-6d 12.S-4g S-6c 13.S-5f S-5d 14.K-6h K-4b 15.P-1f P-1d +16.P-9f P-9d 17.G-4h G-5b 18.P*2d Px2d 19.Rx2d P*2c 20.Rx3d? Bx8h+ +21.Sx8h P*3c 22.R-3f B*2h +# Wing Attack, Reclining Silver 6 +1.P-2f P-8d 2.P-2e P-8e 3.G-7h G-3b 4.S-4h S-6b 5.P-2d Px2d +6.Rx2d P*2c 7.R-2f P-3d 8.P-7f P-8f 9.Px8f Rx8f 10.P*8g R-8d +11.P-4f P-6d 12.S-4g S-6c 13.S-5f S-5d 14.K-6h K-4b 15.P-1f P-1d +16.P-9f P-9d 17.G-5h G-5b 18.P*2d Px2d 19.Rx2d P*2c 20.Rx3d R-8e +21.R-3f R-2e 22.P*2f R-8e +# +# Side Pawn, B*4e Variation 1 +1.P-7f P-3d 2.P-2f P-8d 3.P-2e P-8e 4.G-7h G-3b 5.P-2d Px2d +6.Rx2d P-8f 7.Px8f Rx8f 8.Rx3d Bx8h+ 9.Sx8h B*4e? 10.R-2d Bx6g+ +11.Gx6g Rx8h+ 12.Rx2a+ +Rx9i 13.+Rx3a Gx3a 14.B*3c +# Side Pawn, B*4e Variation 2 +1.P-7f P-3d 2.P-2f P-8d 3.P-2e P-8e 4.G-7h G-3b 5.P-2d Px2d +6.Rx2d P-8f 7.Px8f Rx8f 8.Rx3d Bx8h+ 9.Sx8h B*4e? 10.R-2d Bx6g+? +11.Gx6g Rx8h+ 12.Rx2a+ +Rx8i 13.P*6i N*5e 14.G-6h S*6g 15.G6h-5h Sx5h+ +16.Gx5h G*6g 17.G-4h +R-7h 18.S*5f +# Side Pawn, B*4e Variation 3 +1.P-7f P-3d 2.P-2f P-8d 3.P-2e P-8e 4.G-7h G-3b 5.P-2d Px2d +6.Rx2d P-8f 7.Px8f Rx8f 8.Rx3d Bx8h+ 9.Sx8h B*4e? 10.R-2d P*2c +11.R-2h +# Side Pawn, B*4e Variation 4 +1.P-7f P-3d 2.P-2f P-8d 3.P-2e P-8e 4.G-7h G-3b 5.P-2d Px2d +6.Rx2d P-8f 7.Px8f Rx8f 8.Rx3d Bx8h+ 9.Sx8h P*2h 10.Sx2h B*4e +11.R-2d P*2c 12.B*7g Rx8h+ 13.Bx8h Px2d 14.Bx1a+ +# Side Pawn, B*4e Variation 5 +1.P-7f P-3d 2.P-2f P-8d 3.P-2e P-8e 4.G-7h G-3b 5.P-2d Px2d +6.Rx2d P-8f 7.Px8f Rx8f 8.Rx3d Bx8h+ 9.Sx8h P*2h 10.Sx2h B*4e +11.R-2d P*2c 12.P*8g? Rx7f 13.P*7g R-6f 14.K-6h Px2d 15.Px6f +# +# King's Head Vanguard Pawn vs. Ranging Rook 1 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.S6h-5g S-4c +11.P-7e? P-6d 12.G6i-6h S-6c 13.S-6f R-7b +# King's Head Vanguard Pawn vs. Ranging Rook 2 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.S4h-5g S-4c +11.P-7e P-6d? 12.S-7g S-6c 13.S-7f R-7b 14.S-6f +# King's Head Vanguard Pawn vs. Ranging Rook 3 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.P-2e B-3c +11.S4h-5g S-4c 12.P-7e? R-2b 13.S-7g G-3b 14.S-7f? P-2d 15.Px2d Rx2d +# King's Head Vanguard Pawn vs. Ranging Rook 4 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.S4h-5g S-4c +11.P-7e G4a-5b 12.S-7g P-5d 13.S-7f P-3e 14.P-2e B-3c 15.P-1f P-1d +16.B-7g R-3b 17.P-6f B-4b 18.R-2f R-3d 19.K-8h N-3c 20.G-7h +# +# Quick-Attack Line vs. Ranging Rook 1 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.P-3f G4a-5b +11.S6h-5g S-4c 12.P-2e B-3c 13.S-4f P-6d? 14.P-3e Px3e? 15.Sx3e P*3d +16.P-2d Px3e 17.Px2c+ +# Quick-Attack Line vs. Ranging Rook 2 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.P-3f G4a-5b +11.S6h-5g S-4c 12.P-2e B-3c 13.S-4f P-6d? 14.P-3e P-4e? 15.Bx3c+ Nx3c +16.S-5e Px3e 17.P-2d +# Quick-Attack Line vs. Ranging Rook 3 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.P-3f G4a-5b +11.S6h-5g S-4c 12.P-2e B-3c 13.S-4f P-6d? 14.P-3e R-3b 15.Px3d Sx3d +16.R-3h P-4e 17.Bx3c+ Rx3c 18.S-5e +# Quick-Attack Line vs. Ranging Rook 4 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.P-3f G4a-5b +11.S6h-5g S-4c 12.P-2e B-3c 13.S-4f P-5d 14.P-3e R-3b 15.G6i-6h +# Quick-Attack Line vs. Ranging Rook 5 +1.P-7f P-3d 2.P-2f P-4d 3.P-5f S-3b 4.S-4h R-4b 5.K-6h K-6b +6.G4i-5h K-7b 7.K-7h K-8b 8.S-6h S-7b 9.P-9f P-9d 10.P-3f G4a-5b +11.S6h-5g S-4c 12.P-2e B-3c 13.S-4f P-5d 14.P-3e R-3b 15.R-3h? P-4e +16.Bx3c+ Rx3c +# +# Fortress Opening - the Basics 1 +1.P-7f P-8d 2.S-6h P-3d 3.S-7g +# Fortress Opening - the Basics 2 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.G-7h? G-3b +6.G-5h K-4a 7.P-6f? P-6d 8.K-6i P-7d 9.G5h-6g S-6c 10.P-5f S-5d +11.B-7i R-6b 12.B-6h N-7c 13.K-7i? N-8e 14.S-8h P-6e +# Fortress Opening - the Basics 3 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f P-6d? +6.P-2e B-3c 7.P-5f +# Fortress Opening - the Basics 4 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f P-8e +6.P-5f? P-8f 7.Px8f Rx8f 8.Sx8f Bx8h+ +# Fortress Opening - the Basics 5 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f P-8e +6.P-5f? P-8f 7.Px8f Rx8f 8.G-7h Bx7g+ Nx7g S*8g +# Fortress Opening - the Basics 6 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-1d 14.P-2e P-8e 15.S-3g G5b-4c +16.G5h-6g P-6d? 17.P-3e Px3e 18.Bx3e S-6c 19.S-3f B-4b 20.P-4f P*3d +21.B-2f +# Fortress Opening - the Basics 7 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-1d 14.P-2e P-8e 15.S-3g B-6d +16.L-1g B-7c 17.R-1h S-5c? 18.P-1e Px1e 19.Lx1e Lx1e 20.Rx1e P*1c +21.R-1h G5b-4c 22.P*1b +# Fortress Opening - the Basics 8 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-1d 14.P-2e P-8e 15.S-3g B-6d +16.L-1g B-7c 17.R-1h S-5c? 18.P-1e Px1e 19.Lx1e P*1c 20.Lx1c+ Nx1c +21.Bx1c+ Lx1c 22.Rx1c+ S-2b 23.+R-1h B-5a 24.P*1d +# Fortress Opening - the Basics 9 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-1d 14.P-2e P-8e 15.S-3g B-6d +16.L-1g K-3a? 17.R-1h K-2b 18.S-2f G5b-4c 19.P-1e Px1e 20.Sx1e +# Fortress Opening - the Basics 10 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-1d 14.P-2e P-8e 15.S-3g B-6d +16.L-1g B-7c 17.R-1h G-2b 18.G5h-6g S-5c 19.B-5g P-6d 20.S-2f B-8d +21.K-7i N-7c 22.R-3h G-4c 23.P-3e Px3e 24.Sx3e P*3d 25.S-4f K-3a +# +# Fortress Opening, N-3g Variation 1 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e B-6d 15.N-3g G5b-4c +16.L-1g K-3a 17.R-1h B-7c? 18.P-1d Px1d 19.Lx1d P*1c 20.Lx1c Nx1c +21.Bx1c+ Lx1c Rx1c+ +# Fortress Opening, N-3g Variation 2 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e B-6d 15.N-3g G5b-4c +16.L-1g K-3a 17.R-1h K-2b 18.B-6h S-7c? 19.P-6e B-4b 20. N-2e +# Fortress Opening, N-3g Variation 3 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e B-6d 15.N-3g G5b-4c +16.L-1g K-3a 17.R-1h K-2b 18.B-6h B-7c 19.G5h-6g S-5c? 20.K-7i P-6d +21.K-8h B-8d 22.N-2e +# Fortress Opening, N-3g Variation 4 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e B-6d 15.N-3g G5b-4c +16.L-1g K-3a 17.R-1h K-2b 18.B-6h B-7c 19.G5h-6g S-2d 20.P-4f B-8d +# Fortress Opening, N-3g Variation 5 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e S-7c 15.G5h-6g G5b-4c +16.N-3g S-6d 17.B-5g P-7e 18.P-6e Sx6e 19.Px7e +# Fortress Opening, N-3g Variation 6 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e S-7c 15.G5h-6g G5b-4c +16.N-3g S-6d 17.B-5g P-7e 18.Px7e? Sx7e 19.P*7f P-8f 20.Px8f Sx8f +21.Sx8f Bx8f 22.P*8g B-4b +# Fortress Opening, N-3g Variation 7 +1.P-7f P-8d 2.S-7h P-3d 3.S-7g S-6b 4.S-4h S-4b 5.P-2f S-3c +6.G-7h G-3b 7.G-5h G-5b 8.P-5f P-5d 9.P-3f P-7d 10.B-7i B-3a +11.K-6i K-4a 12.P-6f P-4d 13.P-1f P-8e 14.P-1e S-7c 15.G5h-6g G5b-4c +16.N-3g P-7e? 17.Px7e Bx7e 18.P-6e B-4b 19.B-4f P*7d 20.S-6f +# +# +1.P7g-7f P3c-3d 2.P6g-6f P3d-3e 3.S7i-6h R8b-3b 4.S6h-6g P3e-3f 5.P3gx3f R3bx3f +6.P*3g R3f-3d 7.B8h-7g S3a-4b 8.R2h-8h K5a-6b 9.G4i-4h K6b-7b 10.K5i-4i G4a-5b +11.K4i-3h G6a-6b 12.P8g-8f P1c-1d +# +1.P7g-7f P3c-3d 2.P7f-7e K5a-4b 3.P6g-6f S7a-6b 4.R2h-7h P6c-6d 5.K5i-4h P8c-8d +6.S7i-6h P8d-8e 7.R7h-7f P6d-6e 8.S6h-7g P6ex6f 9.S7gx6f P*6e 10.S6f-7g S6b-6c +11.G6i-7h K4b-3b +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P9g-9f P1c-1d 8.P1g-1f P6c-6d 9.S3i-3h S7b-6c 10.P9f-9e P3c-3d +11.P7g-7f S6c-5d 12.K5i-4h P4c-4d 13.P7f-7e G6a-7b 14.R2f-7f S3a-4b +# Tanaka p.20 Double Fortress +1. 7g7f 8c8d 2. 7i6h 3c3d 3. 6h7g 7a6b 4. 2g2f 3a4b 5. 3i4h 4a3b +6. 6i7h 5c5d 7. 5i6i 5a4a 8. 5g5f 7c7d 9. 3g3f 6b5c 10. 2f2e 4b3c +# Tanaka, p.20 + 1. 7g7f 8c8d 2. 7i6h 3c3d 3. 6h7g 7a6b 4. 2g2f 3a4b 5. 3i4h 4a3b + 6. 6i7h 5c5d 7. 5i6i 5a4a 8. 5g5f 7c7d 9. 3g3f 6b5c 10. 2f2e 4b3c +11. 4i5h 2b3a 12. 6g6f 6a5b 13. 8h7i 4c4d 14. 5h6g 3a4b 15. 7i4f 5c6d +# Tanaka, p.31 +2g2f 8c8d 2f2e 8d8e 6i7h 4a3b 2e2d 2c2d 2h2d P*2c +2d2f 7a7b 9g9f 1c1d 2f3f 6c6d 7g7f 8e8f 8g8f 8b8f +7f7e 8f8b 8i7g 7b6c 5i4h 3a4b 8h9g 6a7b P*8e 4c4d +3f7f 4d4e 7i6h 3c3d 6g6f 5a4a 5g5f 4a3a 4h3h 2b3c +# Tanaka, p.40 +7g7f 8c8d 2g2f 8d8e 2f2e 4a3b 8h7g 3c3d 7i6h 2b7g+ +6h7g 3a2b 6i7h 2b3c 3i3h 7a6b 5i6h 5a4b 3h2g 7c7d +2g2f 6b7c 2f1e 3c2b 2e2d 2c2d 1e2d P*2c 2d1e 7c6d +7g8h 1c1d 1e2f 7d7e 7f7e 6d7e 2f2e 8e8f 8g8f 8b8f +# Tanaka, p.50 +7g7f 8c8d 5g5f 3c3d 5f5e 7a6b 2h5h 5a4b 5i4h 4b3b +4h3h 3a4b 8h7g 6c6d 7i6h 6b6c 6h5g 6c7d 5g5f 6a5b +6g6f 8b6b 6i7h 6d6e 6f6e 7d6e 5f6e 6b6e 5h6h 6e6h+ +7h6h P*6g 6h6g R*7i 6g6h 7i8i+ S*7h N*4f 4g4f S*4g +# Tanaka, p.70 +7g7f 8c8d 7i6h 3c3d 6h7g 7a6b 3i4h 5c5d 5g5f 6a5b +6i7h 5a4b 5i6i 4b3b 3g3f 3a4b 8h7i 4b3c 4h3g 2b3a +3f3e 3d3e 7i3e 3a6d 2h3h P*3d 3e6h 4c4d 4i5h 5b4c +# Tanaka, p.80 +7g7f 8c8d 7i6h 3c3d 6h7g 7a6b 3i4h 5c5d 5g5f 6a5b +6i7h 5a4b 5i6i 4b3b 4i5h 3a4b 8h7i 7c7d 6g6f 4b3c +3g3f 2b3a 1g1f 4c4d 1f1e 5b4c 5h6g 6b7c 1i1g 7c6d +# Tanaka, p.92 +7g7f 8c8d 7i6h 3c3d 6h7g 7a6b 2g2f 3a4b 3i4h 4a3b +6i7h 5a4a 5i6i 5c5d 5g5f 7c7d 4i5h 6a5b 8h7i 4b3c +6g6f 2b3a 3g3f 4c4d 5h6g 5b4c 7i4f 3a6d 2f2e 4a3a +6i7i 3a2b 7i8h 8d8e 4h3g 6b7c 1g1f 9c9d 4f6d 7c6d +# Tanaka, p.102 +7g7f 3c3d 2g2f 4c4d 3i4h 3a3b 5g5f 8b4b 5i6h 5a6b +6h7h 6b7b 4i5h 7b8b 3g3f 7a7b 9g9f 9c9d 2f2e 2b3c +7i6h 3b4c 6h5g 4a5b 5g4f 4c3b 4f3g 5c5d 3g2f 3b4c +3f3e 4b3b 2h3h 3c4b 4g4f 4b6d 4h5g 5b5c 6g6f 7c7d +# +1. 7g7f 8c8d 2. 7i6h 3c3d 3. 6h7g 7a6b 4. 2g2f 3a4b 5. 3i4h 4a3b +6. 6i7h 5a4a 7. 5i6i 5c5d 8. 5g5f 6a5b 9. 4i5h 4b3c 10. 8h7i 2b3a +11. 6g6f 4c4d 12. 3g3f 7c7d 13. 1g1f 6b7c 14. 5h6g 5b4c 15. 1f1e 8d8e +# +1. 7g7f 8c8d 2. 7i6h 3c3d 3. 6h7g 3d3e 4. 5g5f 8b3b 5. 3i4h 5a6b +6. 5i6h 7a7b 7. 6h7h 6b7a 8. 4i5h 7c7d 9. 2g2f 4a5b 10. 2f2e 3b3d +11. 4h5g 2a3c 12. 2h2f 1c1d 13. 8h7i 2b1c 14. 1g1f 3a4b 15. 5g4f 8a7c +16. 6g6f 6c6d 17. 9g9f 4b5a 18. 7h8h 5a6b 19. 6i7h 6b6c 20. 5h6g 9c9d +# +1. 2g2f 8c8d 2. 2f2e 8d8e 3. 6i7h 4a3b 4. 2e2d 2c2d 5. 2h2d P*2c +6. 2d2f 7a6b 7. 9g9f 3c3d 8. 2f3f 3b3c 9. 7g7f 5a4a 10. 3i3h 1c1d +11. 3f2f 3c3b 12. 4g4f 8e8f 13. 8g8f 8b8f 14. P*8g 8f8b 15. 3h4g 5c5d +16. 5i6i 6b5c 17. 4i5h 5d5e 18. 7i6h 5c5d 19. 3g3f 5d6e 20. 6h7g 5e5f +# +1. 7g7f 8c8d 2. 7i6h 3c3d 3. 6h7g 7a6b 4. 3i4h 3a4b 5. 6i7h 4a3b +6. 5i6i 5a4a 7. 5g5f 5c5d 8. 2g2f 6a5b 9. 3g3f 4c4d 10. 4i5h 4b3c +11. 8h7i 2b3a 12. 6g6f 7c7d 13. 1g1f 6b7c 14. 5h6g 5b4c 15. 4h3g 7d7e +# +1. 2g2f 8c8d 2. 2f2e 8d8e 3. 6i7h 4a3b 4. 2e2d 2c2d 5. 2h2d P*2c +6. 2d2f 7a6b 7. 9g9f 1c1d 8. 7g7f 3c3d 9. 8i7g 2b4d 10. 2f5f 3a4b +11. 3i3h 6c6d 12. 5i4h 6b6c 13. 7f7e 5a4a 14. 8h9g 6a7b 15. 8g8f 8e8f +# +1. 7g7f 8c8d 2. 2h7h 3c3d 3. 6g6f 8d8e 4. 8h7g 5a4b 5. 7i6h 4b3b +6. 5i4h 7a6b 7. 4h3h 6a5b 8. 3h2h 7c7d 9. 3i3h 5c5d 10. 5g5f 1c1d +11. 1g1f 3a4b 12. 6i5h 4b5c 13. 4g4f 9c9d 14. 9g9f 4a4b 15. 3g3f 7d7e +# +1. 2g2f 8c8d 2. 2f2e 8d8e 3. 6i7h 4a3b 4. 2e2d 2c2d 5. 2h2d P*2c +6. 2d2f 7a6b 7. 9g9f 1c1d 8. 3i3h 6c6d 9. 4g4f 6b6c 10. 3h4g 3c3d +11. 4g5f 6c5d 12. 5i6h 5a4b 13. 4i4h 8e8f 14. 8g8f 8b8f 15. P*8g 8f8d +# +1. 7g7f 8c8d 2. 7i6h 3c3d 3. 6h7g 7a6b 4. 2g2f 3a4b 5. 3i4h 4a3b +6. 6i7h 5a4a 7. 5i6i 5c5d 8. 5g5f 6a5b 9. 3g3f 4c4d 10. 4g4f 5b4c +11. 4h4g 8d8e 12. 2i3g 1c1d 13. 9g9f 9c9d 14. 4i5h 7c7d 15. 2f2e 4b3c +# +1. 2g2f 8c8d 2. 2f2e 8d8e 3. 6i7h 4a3b 4. 2e2d 2c2d 5. 2h2d P*2c +6. 2d2f 7a7b 7. 9g9f 1c1d 8. 7g7f 8e8f 9. 8g8f 8b8f 10. 8i7g 9c9d +11. 7g6e 8f8e 12. 6e5c+ P*8f 13. 2f5f 5a4a 14. 5f5e 8e5e 15. 8h5e 8f8g+ +# +1. 7g7f 3c3d 2. 2g2f 4c4d 3. 3i4h 3a4b 4. 5i6h 8b5b 5. 6h7h 5a6b +6. 4i5h 6b7b 7. 5g5f 4b4c 8. 2f2e 2b3c 9. 3g3f 7b8b 10. 7i6h 7a7b +11. 6h5g 4a3b 12. 9g9f 9c9d 13. 6i6h 5c5d 14. 4g4f 6c6d 15. 4h3g 7c7d +# +1. 2g2f 8c8d 2. 2f2e 8d8e 3. 6i7h 4a3b 4. 2e2d 2c2d 5. 2h2d P*2c +6. 2d2f 7a7b 7. 3i3h 6c6d 8. P*2d 2c2d 9. 2f2d 1c1d 10. 7g7f 8e8f +11. 8g8f 8b8f 12. 1g1f 6a7a 13. 1f1e 1d1e 14. P*1d P*2c 15. 2d2e 1e1f +# +# +1.P2g-2f P3c-3d 2.P2f-2e B2b-3c 3.P7g-7f P4c-4d 4.S3i-4h R8b-3b 5.P3g-3f S3a-4b +6.K5i-6h K5a-6b 7.K6h-7h K6b-7b 8.P5g-5f P5c-5d 9.G4i-5h G4a-5b 10.S7i-6h S4b-5c +11.P1g-1f P1c-1d 12.P4g-4f K7b-8b 13.N2i-3g S7a-7b +# +1.P2g-2f P3c-3d 2.P2f-2e B2b-3c 3.P7g-7f P4c-4d 4.S3i-4h S3a-4b 5.P5g-5f S4b-4c +6.S4h-5g P5c-5d 7.B8h-7g G4a-3b 8.K5i-6h S7a-6b 9.S7i-7h S6b-5c 10.P6g-6f P7c-7d +11.S7h-6g K5a-4a 12.G6i-7h R8b-5b 13.P3g-3f N8a-7c +# +1.P7g-7f P3c-3d 2.P2g-2f P4c-4d 3.S3i-4h S3a-3b 4.P5g-5f R8b-4b 5.K5i-6h K5a-6b +6.K6h-7h S7a-7b 7.S4h-5g G4a-5b 8.B8h-7g K6b-7a 9.K7h-8h S3b-4c 10.L9i-9h S4c-5d +11.P6g-6f K7a-8b 12.K8h-9i P6c-6d 13.S7i-8h P7c-7d 14.G6i-7i G5b-6c +# +1.P7g-7f P3c-3d 2.P2g-2f P4c-4d 3.S3i-4h S3a-4b 4.P5g-5f S4b-4c 5.K5i-6h P3d-3e +6.K6h-7h R8b-3b 7.P2f-2e B2b-3c 8.G4i-3h K5a-6b 9.G3h-2g K6b-7b 10.P3g-3f B3c-4b +11.P3fx3e R3bx3e 12.G2g-2f R3e-3a +# +1.P7g-7f P3c-3d 2.P2g-2f P4c-4d 3.S3i-4h S3a-3b 4.P5g-5f R8b-4b 5.K5i-6h K5a-6b +6.K6h-7h S7a-7b 7.G4i-5h K6b-7a 8.P9g-9f P9c-9d 9.S4h-5g G4a-5b 10.S7i-6h K7a-8b +11.P5f-5e S3b-4c 12.P2f-2e B2b-3c +# +1.P2g-2f P3c-3d 2.P7g-7f P4c-4d 3.S3i-4h S3a-3b 4.P5g-5f R8b-4b 5.K5i-6h K5a-6b +6.K6h-7h S7a-7b 7.G4i-5h K6b-7a 8.P3g-3f G4a-5b 9.S7i-6h P9c-9d 10.P9g-9f K7a-8b +11.P2f-2e B2b-3c 12.P1g-1f P1c-1d +# +1.P7g-7f P3c-3d 2.P2g-2f P4c-4d 3.S3i-4h S3a-3b 4.P5g-5f R8b-4b 5.K5i-6h K5a-6b +6.K6h-7h S7a-7b 7.G4i-5h K6b-7a 8.P9g-9f P9c-9d 9.P8g-8f S3b-4c 10.K7h-8g G4a-5b +11.S7i-7h P6c-6d 12.P2f-2e B2b-3c 13.S4h-5g K7a-8b 14.S5g-6f G5b-6c +# +1.P2g-2f P3c-3d 2.P7g-7f P4c-4d 3.S3i-4h S3a-4b 4.G4i-5h S4b-4c 5.K5i-6h P5c-5d +6.P5g-5f P8c-8d 7.S7i-7h S7a-6b 8.P2f-2e G4a-3b 9.P2e-2d P2cx2d 10.R2hx2d P*2c +11.R2d-2h S6b-5c 12.S7h-7g P7c-7d 13.P6g-6f P6c-6d 14.K6h-7h G6a-5b +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P9c-9d 9.P9g-9f P3c-3d 10.P7g-7f K5a-4b +11.K5i-6h P8e-8f 12.P8gx8f R8bx8f 13.P*8g R8f-8b +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h S3a-4b 5.P5g-5f P5c-5d +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.G4i-5h G6a-5b 9.P6g-6f S4b-3c 10.B8h-7i B2b-3a +11.P3g-3f P4c-4d 12.G5h-6g G5b-4c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h P5c-5d 5.P5g-5f S3a-4b +6.G6i-7h G6a-5b 7.K5i-6i G4a-3b 8.G4i-5h K5a-4a 9.P6g-6f P7c-7d 10.P3g-3f P5d-5e +11.S4h-5g S6b-5c 12.P2g-2f S5c-5d +# +1.P7g-7f P3c-3d 2.P2g-2f P4c-4d 3.S3i-4h S3a-3b 4.P5g-5f P5c-5d 5.G4i-5h S7a-6b +6.G6i-7h G6a-5b 7.S7i-6h P8c-8d 8.K5i-6i G5b-4c 9.P4g-4f S3b-3c 10.P3g-3f G4a-3b +11.S4h-4g K5a-4a +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-6b 7.P1g-1f P1c-1d 8.S3i-3h P3c-3d 9.P7g-7f P5c-5d 10.P4g-4f S6b-5c +11.B8hx2b+ S3ax2b 12.S7i-8h P8e-8f 13.P8gx8f R8bx8f 14.P*8g R8f-8b 15.P3g-3f G6a-5b +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-6b 7.P1g-1f P1c-1d 8.S3i-3h P3c-3d 9.P7g-7f P8e-8f 10.P8gx8f R8bx8f +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-6b 7.P1g-1f P1c-1d 8.S3i-3h P3c-3d 9.P7g-7f P6c-6d 10.R2f-3f B2bx8h+ +11.S7ix8h +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-6b 7.S3i-3h P6c-6d 8.P*2d P2cx2d 9.R2fx2d P1c-1d 10.P7g-7f P8e-8f +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.S3i-3h P6c-6d 8.P1g-1f P1c-1d 9.P7g-7f P3c-3d 10.R2f-3f B2bx8h+ +11.S7ix8h B*2h +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.S3i-3h P6c-6d 8.P1g-1f P1c-1d 9.P7g-7f P8e-8f 10.P8gx8f R8bx8f +11.P*2d P2cx2d 12.R2fx2d S7b-6c 13.P1f-1e P1dx1e 14.P*1d P*2c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P2g-2f S3a-4b 5.S3i-4h G4a-3b +6.G6i-7h P5c-5d 7.P5g-5f K5a-4a 8.K5i-6i G6a-5b 9.P3g-3f P7c-7d 10.G4i-5h S4b-3c +11.B8h-7i B2b-3a 12.P6g-6f P4c-4d +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.P2f-2e G4a-3b 4.G6i-7h P8e-8f 5.P8gx8f R8bx8f +6.P2e-2d P2cx2d 7.R2hx2d P*2c 8.R2d-2f S7a-6b 9.P1g-1f P1c-1d 10.S3i-3h R8f-8b +11.P*8g P6c-6d 12.P4g-4f S6b-6c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h S3a-4b 5.P5g-5f G4a-3b +6.G4i-5h K5a-4a 7.G6i-7h P5c-5d 8.K5i-6i G6a-5b 9.P6g-6f P6c-6d 10.G5h-6g S6b-5c +11.P2g-2f R8b-6b 12.S4h-5g P7c-7d +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.S3i-3h P9c-9d 8.P1g-1f P1c-1d 9.P9g-9f P3c-3d 10.R2f-3f G3b-3c +11.S7i-6h P6c-6d 12.S3h-2g S3a-3b +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S7a-7b 8.P4g-4f P6c-6d 9.S3h-4g S7b-6c 10.G4i-5h P1c-1d +11.P1g-1f P9c-9d 12.P9g-9f G6a-5b +# +1.P2g-2f P3c-3d 2.P7g-7f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f 8.R2dx3d N2a-3c 9.R3d-3f R8f-8d 10.R3f-2f N3c-4e +11.R2f-5f P*2h 12.S3ix2h B2bx8h+ 13.S7ix8h B*9b +# +1.P2g-2f P3c-3d 2.P7g-7f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f 8.R2dx3d B2bx8h+ 9.S7ix8h P*2h 10.S3ix2h B*4e +# +1.P2g-2f P3c-3d 2.P7g-7f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f 8.R2dx3d B2b-3c +# +1.P2g-2f P3c-3d 2.P7g-7f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f 8.R2dx3d B2bx8h+ 9.S7ix8h R8fx7f +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.G4i-5h P6c-6d 9.P2g-2f P8d-8e 10.S6h-7g P5d-5e +11.P5fx5e B2bx5e 12.P2f-2e B5e-2b 13.G5h-6g S6b-6c 14.B8h-7i P7c-7d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.S6h-7g P7c-7d 9.P2g-2f G6a-5b 10.P2f-2e S4b-3c +11.B8h-7i P8d-8e 12.P3g-3f B2b-3a 13.B7i-4f B3a-6d 14.S4h-3g P4c-4d 15.K5i-6h S6b-7c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f G5b-4c 13.B7i-6h P7c-7d 14.K6i-7i B3a-6d 15.N2i-3g K4a-3a +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f P7c-7d 13.B7i-6h G5b-4c 14.K6i-7i B3a-6d 15.N2i-3g +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f G5b-4c 13.B7i-6h P7c-7d 14.K6i-7i B3a-6d 15.S4h-3g K4a-3a +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.S6h-7g P7c-7d 9.P2g-2f G6a-5b 10.B8h-7i S4b-3c +11.P3g-3f B2b-3a 12.K5i-6h P7d-7e 13.P7fx7e B3ax7e 14.K6h-7h B7e-6d 15.N2i-3g P4c-4d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h P5c-5d 5.P5g-5f S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g P7c-7d 9.B8h-7i S4b-3c 10.K5i-6h P6c-6d +11.K6h-7h S6b-6c 12.P3g-3f S3c-4d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.S6h-7g P7c-7d 9.B8h-7i P6c-6d 10.G6i-7h S6b-6c +11.K5i-6i +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g P7c-7d 9.B8h-7i S4b-3c 10.P3g-3f B2b-3a +11.K5i-6h P7d-7e 12.P7fx7e B3ax7e 13.P6f-6e B7e-4b 14.K6h-7h S6b-7c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f G5b-4c 13.B7i-6h P7c-7d +# +1.P7g-7f P8c-8d 2.P2g-2f G4a-3b 3.G6i-7h P8d-8e 4.B8h-7g P3c-3d 5.S7i-8h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S7a-7b 8.P4g-4f P6c-6d 9.S3h-4g S7b-6c 10.P6g-6f P4c-4d +11.G4i-5h G6a-5b 12.K5i-6h K5a-4a 13.K6h-7i K4a-3a +# +1.P7g-7f P8c-8d 2.B8h-7g P3c-3d 3.S7i-6h S7a-6b 4.S3i-3h P6c-6d 5.P4g-4f S6b-6c +6.S3h-4g G4a-3b 7.G6i-7h G6a-5b 8.S4g-5f S6c-5d 9.R2h-4h K5a-4a 10.P4f-4e B2bx7g+ +11.S6hx7g S3a-4b 12.K5i-6h K4a-3a 13.P3g-3f P7c-7d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h K5a-4b +6.P2g-2f S3a-3b 7.G4i-5h G6a-5b 8.G5h-6g S3b-3c 9.S6h-7g K4b-3b 10.K5i-6h P4c-4d +11.K6h-7h G5b-4c 12.B8h-7i B2b-3a 13.P3g-3f P7c-7d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g P4c-4d +11.B8h-7i B2b-3a 12.P3g-3f G5b-4c 13.B7i-6h P7c-7d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.S6h-7g P7c-7d 9.B8h-7i P6c-6d 10.P2g-2f S6b-6c +11.P2f-2e R8b-5b 12.G6i-7h N8a-7c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h P5c-5d 5.P5g-5f S3a-4b +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.P2g-2f G6a-5b 9.P2f-2e S4b-3c 10.P3g-3f P4c-4d +11.S4h-3g G5b-4c 12.S3g-4f S6b-5c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S6b-5c +6.G6i-7h S5c-6d 7.P2g-2f S3a-4b 8.K5i-6i G4a-3b 9.P2f-2e S4b-3c 10.P3g-3f G6a-5b +11.G4i-5h K5a-4a 12.P6g-6f P4c-4d 13.G5h-6g G5b-4c +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P6c-6d 9.P7g-7f P8e-8f 10.P8gx8f R8bx8f +11.P*8g R8f-8b 12.P3g-3f P3c-3d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h P5c-5d 5.P5g-5f S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g P7c-7d 9.P2g-2f S4b-3c 10.B8h-7i B2b-3a +11.K5i-6h S6b-7c 12.K6h-7h S7c-6d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f P7c-7d 13.B7i-6h P9c-9d 14.K6i-7i P9d-9e 15.K7i-8h L9a-9c +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h B2bx7g+ 5.S8hx7g S3a-2b +6.S3i-3h S2b-3c 7.P4g-4f S7a-7b 8.S3h-4g K5a-4b 9.G6i-7h G4a-3b 10.P6g-6f G6a-5b +11.P9g-9f P7c-7d 12.S4g-5f S7b-7c +# +1.P7g-7f P3c-3d 2.P2g-2f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P*2c 7.R2d-2h B2bx8h+ 8.S7ix8h +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f G5b-4c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h P7c-7d 9.K5i-6i S6b-5c 10.P2g-2f P8d-8e +11.S6h-7g P5d-5e 12.P5fx5e B2bx5e +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S7a-7b 8.P4g-4f P6c-6d 9.S3h-4g S7b-6c 10.G4i-5h P4c-4d +11.K5i-6h G6a-5b 12.K6h-7i K5a-4a 13.P9g-9f P1c-1d +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.S3i-3h P3c-3d 8.P9g-9f P1c-1d 9.P1g-1f P9c-9d +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P3c-3d 9.P7g-7f P8e-8f 10.P8gx8f R8bx8f +11.P*8g R8f-8b +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.P9g-9f P3c-3d 9.S3i-3h P6c-6d 10.R2f-3f G3b-3c +11.S3h-2g S7b-6c 12.G4i-3h P4c-4d 13.R3f-2f G6a-5b 14.S2g-3f G5b-4c +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P3c-3d 9.P7g-7f P8e-8f 10.P8gx8f R8bx8f +11.P*8g R8f-8b +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g P7c-7d 9.G6i-7h G6a-5b 10.B8h-7i S4b-3c +11.K5i-6i B2b-3a 12.B7i-6h P4c-4d +# +1.P7g-7f P3c-3d 2.P2g-2f P4c-4d 3.S3i-4h S3a-3b 4.P5g-5f P5c-5d 5.G4i-5h S7a-6b +6.S7i-7h G6a-5b 7.S7h-7g S3b-3c 8.B8h-7i G5b-4c 9.K5i-6h B2b-3a 10.K6h-7h K5a-4b +11.P6g-6f K4b-3b 12.G5h-6g P7c-7d 13.K7h-8h S6b-7c 14.S4h-5g K3b-2b +# +1.P7g-7f P3c-3d 2.P2g-2f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i S4b-3c 10.S6h-7g P4c-4d +11.B8h-7i B2b-3a 12.P3g-3f P7c-7d 13.B7i-6h G5b-4c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g P7c-7d 9.G6i-7h G6a-5b 10.K5i-6i S4b-3c +11.B8h-7i B2b-3a 12.P3g-3f P4c-4d 13.S4h-3g B3a-6d 14.B7i-6h G5b-4c +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S7a-6b 8.P4g-4f P6c-6d 9.S3h-4g S6b-6c 10.P6g-6f P4c-4d +11.G4i-5h G6a-5b 12.K5i-6h K5a-4a 13.K6h-7i S6c-5d 14.S4g-5f P7c-7d 15.P3g-3f K4a-3a +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.P7g-7f P8e-8f 9.P8gx8f R8bx8f 10.S3i-3h R8f-8b +11.P*8g P6c-6d 12.P3g-3f P3c-3d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g G6a-5b 9.G6i-7h S4b-3c 10.K5i-6i B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f G5b-4c +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P9c-9d 9.P9g-9f P3c-3d 10.P7g-7f K5a-4b +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S7a-7b 8.P4g-4f S4b-3c 9.S3h-4g K5a-4b 10.G4i-5h S7b-8c +11.P6g-6f S8c-8d 12.P9g-9f P9c-9d 13.P3g-3f K4b-3a 14.N2i-3g P7c-7d 15.K5i-4h P4c-4d +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P9c-9d 9.R2f-5f K5a-4b 10.P3g-3f P3c-3d +11.N2i-3g G6a-5b 12.P7g-7f P6c-6d 13.B8hx2b+ S3ax2b +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.G4i-5h P6c-6d 9.P2g-2f P8d-8e 10.S6h-7g P5d-5e +11.P5fx5e B2bx5e 12.P2f-2e B5e-2b +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-3h P9c-9d 9.K5i-5h P9d-9e 10.R2f-5f S3a-4b +11.P3g-3f K5a-6b +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S7a-7b 8.P4g-4f S4b-3c 9.S3h-4g K5a-4b 10.G4i-5h S7b-8c +11.P6g-6f S8c-8d 12.P9g-9f P9c-9d 13.P3g-3f K4b-3a 14.N2i-3g G6a-5b +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h S3a-4b 5.P5g-5f G4a-3b +6.G4i-5h K5a-4a 7.P6g-6f P5c-5d 8.G5h-6g G6a-5b 9.G6i-7h S4b-3c 10.K5i-6i B2b-3a +11.B8h-7i P4c-4d 12.P3g-3f P7c-7d +# +1.P2g-2f P8c-8d 2.P7g-7f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-3h S4b-3c 8.P4g-4f S7a-7b 9.S3h-4g K5a-4b 10.G4i-5h S7b-8c +11.P3g-3f S8c-8d 12.P9g-9f P9c-9d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h S3a-4b 5.P5g-5f G4a-3b +6.G4i-5h P5c-5d 7.P6g-6f P7c-7d 8.G5h-6g K5a-4a 9.G6i-7h P6c-6d 10.K5i-6i S6b-6c +11.P2g-2f N8a-7c 12.P2f-2e P8d-8e 13.B8h-7i S4b-3c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.S3i-4h S3a-4b 5.P5g-5f P5c-5d +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g G6a-5b 9.G6i-7h S4b-3c 10.K5i-6i B2b-3a +11.B8h-7i P4c-4d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.G4i-5h G6a-5b 9.S6h-7g P7c-7d 10.G5h-6g P6c-6d +11.B8h-7i P8d-8e 12.P3g-3f N8a-7c 13.B7i-4f S4b-5c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.P6g-6f K5a-4a 8.G5h-6g P7c-7d 9.G6i-7h G6a-5b 10.K5i-6i S4b-3c +11.B8h-7i B2b-3a 12.P3g-3f P4c-4d 13.B7i-6h G5b-4c 14.K6i-7i B3a-4b +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i P4c-4d 10.S6h-7g S4b-3c +11.B8h-7i B2b-3a 12.P3g-3f G5b-4c +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-4h P6c-6d 9.K5i-6i S7b-6c 10.P3g-3f P3c-3d +11.P7g-7f S6c-5d 12.G4i-5i P8e-8f 13.P8gx8f R8bx8f 14.P3f-3e R8f-8b 15.N2i-3g P3dx3e +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.P6g-6f S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G4i-5h G4a-3b 7.G5h-6g K5a-4a 8.G6i-7h G6a-5b 9.K5i-6i P4c-4d 10.S6h-7g S4b-3c +11.B8h-7i B2b-3a 12.P3g-3f P7c-7d +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2h-2f S7a-7b +6.P1g-1f P1c-1d 7.P7g-7f P8e-8f 8.P8gx8f R8bx8f 9.P*8g R8f-8b 10.S3i-3h P6c-6d +11.P3g-3f P3c-3d 12.S3h-3g S7b-6c +# +1.P7g-7f P3c-3d 2.P2g-2f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f 8.R2dx3d B2b-3c 9.R3d-3f R8f-8d 10.R3f-2f S3a-2b +11.P*8g +# +1.P7g-7f P3c-3d 2.P2g-2f P8c-8d 3.P2f-2e P8d-8e 4.G6i-7h G4a-3b 5.P2e-2d P2cx2d +6.R2hx2d P8e-8f 7.P8gx8f R8bx8f 8.R2dx3d B2b-3c +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-4h P6c-6d 9.K5i-6i P3c-3d 10.G4i-5i K5a-4b +11.P9g-9f P9c-9d 12.P7g-7f P8e-8f 13.P8gx8f R8bx8f 14.R2f-5f R8f-8b 15.P3g-3f P4c-4d +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.G4i-5h G6a-5b 9.P6g-6f S4b-3c 10.P3g-3f P4c-4d +11.B8h-7i B2b-3a 12.G5h-6g G5b-4c +# +1.P2g-2f P8c-8d 2.P2f-2e P8d-8e 3.G6i-7h G4a-3b 4.P2e-2d P2cx2d 5.R2hx2d P*2c +6.R2d-2f S7a-7b 7.P1g-1f P1c-1d 8.S3i-4h P6c-6d 9.K5i-6i P3c-3d 10.G4i-5i S3a-4b +11.P7g-7f P4c-4d 12.B8h-7g S4b-4c +# +1.P7g-7f P8c-8d 2.S7i-6h P3c-3d 3.S6h-7g S7a-6b 4.P5g-5f P5c-5d 5.S3i-4h S3a-4b +6.G6i-7h G4a-3b 7.K5i-6i K5a-4a 8.G4i-5h G6a-5b 9.P6g-6f P4c-4d 10.P3g-3f S4b-3c +11.B8h-7i B2b-3a 12.G5h-6g G5b-4c +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.P6g-6f S7a-6b 5.S3i-4h G6a-5b +6.P2f-2e B2b-3c 7.G6i-7h G4a-3b 8.G4i-5h K5a-4a 9.K5i-6i S3a-2b 10.P3g-3f +# +1.P7g-7f P8c-8d 2.P2g-2f G4a-3b 3.P2f-2e P3c-3d 4.G6i-7h P8d-8e 5.P2e-2d P2cx2d +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.P2f-2e S4b-3c 8.S3i-4h +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.P2f-2e S4b-3c 8.S3i-4h S7a-6b 9.P4g-4f P6c-6d 10.S4h-4g S6b-6c +11.G4i-5h G6a-5b 12.K5i-6h K5a-4b +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.S3i-4h S4b-3c 8.P4g-4f S7a-6b 9.G4i-5h G6a-5b 10.S4h-4g K5a-4b +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.S7i-8h G4a-3b 5.G6i-7h B2bx7g+ +6.S8hx7g S3a-4b 7.P2f-2e S4b-3c 8.S3i-4h S7a-6b 9.P4g-4f P6c-6d 10.S4h-4g S6b-6c +11.G4i-5h G6a-5b 12.K5i-6h K5a-4b 13.P3g-3f K4b-3a 14.P1g-1f P7c-7d 15.K6h-7i K3a-2b +16.N2i-3g K2b-3a 17.K7i-8h K3a-2b +# +1.P7g-7f P8c-8d 2.P2g-2f P8d-8e 3.B8h-7g P3c-3d 4.P6g-6f S7a-6b 5.S3i-4h G6a-5b +6.G4i-5h G4a-3b 7.G6i-7h B2b-3c 8.S7i-8h K5a-4a 9.G5h-6g S3a-2b +# +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f P1d 8.S3h +P6d 9.P7f P8f 10.Px8f Rx8f 11.P'8g R8b 12.P3f P3d 13.S3g S6c 14.P3e Px3e 15.S4f +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.P6f K4a 8.G6g +G5b 9.B7i S3c 10.P3f B3a 11.K6h P4d 12.K7h G5b-4c 13.K8h B6d 14.S3g P8e 15.G7h +# +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S2b 7.S3h S7b 8.P4f +S3c 9.S4g P6d 10.G5h S6c 11.P3f P1d 12.P1f P7d 13.K6h N7c 14.P6f G6b 15.P2e R8a +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.P6f K4a 8.G6g +P6d 9.P2f S6c 10.P2e P5e 11.Px5e Bx5e 12.G7h P7d 13.K6i S5d 14.P2d Px2d 15.Rx2d +# +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S4b 7.S3h S7b +8.P4f P6d 9.S4g S6c 10.G5h P1d 11.P1f P9d 12.P9f G5b 13.P3f K4a 14.S5f S5d +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.P6f K4a 8.G6g +G5b 9.B7i S6b-5c 10.P2f P6d 11.P2e R6b 12.G7h P6e 13.Px6e Rx6e 14.P'6f R6a +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f G3b 5.S4h K4a 6.G4i-5h P6d 7.G7h B3c 8.K6i +S2b 9.P6f S6c 10.G5h-6g B5a 11.P3f P7d 12.B7i B7c 13.S3g S3c 14.S4f P4d 15.N3g +# +1.P7f P8d 2.S6h(3) P3d 3.S7g S6b 4.S4h(1) S4b 5.P5f P5d 6.G4i-5h G3b(2) +7.P6f(2) K4a 8.G6g P7d(5) 9.G7h(11) G5b(2) 10.K6i S3c(3) 11.B7i(5) B3a(1) +12.B6h(7) P9d(26) 13.P3f(12) P9e(38) 14.K7i(55) N7c(9) 15.K8h(21) L9c(42) +# +1.P7f P8d 2.S6h(1) P3d 3.S7g S6b(1) 4.S4h S4b 5.P5f P5d(3) 6.G4i-5h(1) G3b +7.P6f(1) K4a(1) 8.G6g G5b(1) 9.B7i(8) S6b-5c(55) 10.G7h(26) P6d(5) 11.P2f(7) +R6b(4) 12.P2e(1) P6e(1) 13.Px6e(1) Rx6e 14.P'6f R6a 15.K6i(16) S6d(14) +# +1.P7f P8d(1) 2.P2f P8e(1) 3.B7g P3d 4.S8h G3b(1) 5.G7h Bx7g+(1) 6.Sx7g S4b +7.S3h S7b 8.P4f P6d(11) 9.S4g S6c 10.P6f P4d(3) 11.G5h G5b 12.K6h(1) K4a(1) +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.S4h S4b 5.P5f P5d 6.G4i-5h G3b 7.P6f K4a +8.G6g P7d 9.G7h(5) G5b(5) 10.K6i(1) S3c(3) 11.B7i(2) B3a(1) 12.P3f P4d(18) +# +1.P7f P8d(1) 2.P2f P8e 3.B7g P3d 4.S8h G3b(1) 5.G7h Bx7g+(1) 6.Sx7g S4b 7.S3h +S7b 8.P4f P6d(3) 9.S4g(1) S6c 10.P6f(3) P4d(1) 11.G5h(2) G5b(1) 12.K6h(2) +# +1.P7f P8d(1) 2.S6h P3d 3.S7g S6b(1) 4.S4h(1) S4b 5.P5f P5d 6.G4i-5h G3b(2) +7.P6f K4a(1) 8.G6g P7d(7) 9.G7h(2) G5b(1) 10.K6i(1) S3c 11.B7i B3a(3) 12.P3f +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g(1) S6b 4.P5f(1) P5d 5.S4h S4b 6.G4i-5h G3b +7.P6f(1) K4a 8.G6g(2) G5b(42) 9.P2f(15) P7d(6) 10.B7i(17) P6d(17) 11.G7h(3) +S6b-5c(3) 12.P2e(4) G6c(80) 13.K6i(17) N7c(4) 14.P3f(65) P5e(50) +# +1.P7f P3d(2) 2.P2f P4d 3.S4h(3) S3b(5) 4.P5f R4b 5.K6h K6b 6.K7h K7b +7.G4i-5h K8b(1) 8.P9f P9d(28) 9.S6h S7b(2) 10.P2e(6) B3c 11.P3f G4a-5b(4) +12.S3g(68) S4c(13) 13.P3e(2) Px3e(31) 14.S2f S3d(6) 15.R3h P4e(27) +# +1.P7f P8d 2.P2f P8e(1) 3.B7g P3d 4.S8h G3b(2) 5.G7h Bx7g+(1) 6.Sx7g S4b +7.S3h(2) S7b(2) 8.P4f(2) S8c(3) 9.S4g(10) S8d(1) 10.P9f P9d(7) 11.P6f(9) +K4a 12.P6e(13) P9e(48) 13.Px9e(143) Sx9e 14.Lx9e Lx9e 15.P'9g P'9h(53) +# +1.P7f P8d(1) 2.S6h P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b 6.G7h(1) G3b 7.K6i(1) +K4a 8.G5h P7d(13) 9.P6f(14) S6b-5c(7) 10.P2f(53) P5e(21) 11.Px5e(41) Bx5e +12.P2e(3) S5d(5) 13.G5h-6g(14) R5b(24) 14.P2d(15) Px2d(1) 15.Rx2d P'2c(10) +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b(1) 6.G4i-5h(2) +G3b(2) 7.P6f(1) K4a 8.G6g S6b-5c(36) 9.G7h(9) P5e(28) 10.Px5e(7) Bx5e +11.P2f S5d(67) 12.P2e(6) R5b(26) 13.K6i(14) K3a(23) 14.P'5f(27) B3c(15) +# +1.P7f P8d(1) 2.S6h P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b 6.G4i-5h G3b 7.P6f K4a +8.G6g P7d(3) 9.G7h(8) G5b(3) 10.K6i S3c(1) 11.P3f B3a(1) 12.B7i P4d +# +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S2b 7.S3h S7b 8.P4f +S3c 9.S4g K4b 10.G5h G5b 11.P3f S8c 12.N3g S8d 13.P9f P7d 14.P6f P7e 15.R2i P4d +# +1.P7f P8d 2.S6h P3d 3.P6f S6b 4.P5f P5d 5.S4h S4b 6.G4i-5h G3b 7.G6g P7d 8.P2f +P6d 9.P2e S6c 10.P2d Px2d 11.Rx2d N7c 12.R2h P'2c 13.G7h P8e 14.B7g P4d 15.P4f +# +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f P1d 8.S3h +P6d 9.P7f P8f 10.Px8f Rx8f 11.P'8g R8b 12.P4f S6c 13.S4g P3d 14.S5f S5d 15.P9f +# +1.P7f P8d 2.S6h P3d 3.P6f S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.G6g P7d 8.P2f +P6d 9.P2e S6c 10.P2d Px2d 11.Rx2d N7c 12.R2h P'2c 13.G7h P8e 14.B7g P4d 15.K6i +# +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S2b 7.S3h S3c 8.P4f +S7b 9.S4g K4b 10.G5h G5b 11.P6f S8c 12.P3f S8d 13.P9f P7d 14.N3g P4d 15.R2i S7c +# +1.P7f P3d 2.P6f P3e 3.P5f R3b 4.S4h S4b 5.K6h K6b 6.K7h K7b 7.P9f P4d 8.G4i-5h +S4c 9.G6g P1d 10.B7g K8b 11.K8h L9b 12.S7h K9a 13.P8f S8b 14.S8g R3d 15.G7h B1c +# +1.P7f P3d(4) 2.P2f P4d 3.P2e B3c 4.S4h S3b(3) 5.P5f R4b(2) 6.K6h K6b 7.K7h +K7b 8.G4i-5h(6) K8b(11) 9.P9f(2) S4c(20) 10.S5g(14) G4a-5b(16) 11.P8f(4) +P6d(4) 12.K8g(9) L9b(51) 13.S7h K9a 14.P3f(69) S8b(1) 15.S4f G7a(42) +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b 6.G4i-5h G3b 7.P6f K4a +8.G6g P7d 9.G7h(4) G5b(2) 10.K6i S3c 11.B7i B3a 12.P3f(1) P4d 13.B6h(23) +# +1.P7f P3d(1) 2.P2f P8d(1) 3.P2e P8e 4.G7h G3b 5.P2d Px2d 6.Rx2d P8f(4) 7.Px8f +Rx8f 8.Rx3d(3) Bx8h+(34) 9.Sx8h Rx7f 10.N7g(24) G3c(47) 11.R8d(11) P'8b(5) +12.K5h(33) R2f(9) 13.P'2h K5b 14.G3h(3) G7b(2) 15.P2g R2b 16.R8f(1) P8c(5) +# +1.P2f P8d(2) 2.P2e P8e 3.G7h(2) G3b 4.P2d Px2d 5.Rx2d P'2c(8) 6.R2f S7b +7.P1f(6) P1d(1) 8.P9f(7) P6d(9) 9.S3h(39) S6c(6) 10.P7f(2) P8f(3) 11.Px8f +Rx8f 12.N7g P9d(28) 13.K4h(5) S4b(21) 14.B9g(55) R8b(112) 15.P7e(1) P3d(1) +# +1.P7f G3b(6) 2.P5f(8) P5d(9) 3.R5h(2) S6b(7) 4.P5e(1) Px5e(1) 5.Bx5e K4a +6.B7g P3d(2) 7.P6f P'5e(20) 8.S6h S5c 9.S6g S5d 10.K4h S4b(3) 11.K3h R5b(13) +12.R8h(16) P4d(22) 13.P8f P4e 14.P8e R8b 15.K2h(21) K3a 16.P7e(22) B4d(6) +# +1.P7f P8d(1) 2.S6h P3d(1) 3.P6f S6b(2) 4.P5f P5d 5.S4h(2) S4b(2) +6.G4i-5h G3b(2) 7.G6g(1) K4a(8) 8.G7h(3) G5b(5) 9.K6i(1) S3c(1) +10.S7g(1) B3a(1) 11.B7i(2) P4d(2) 12.P3f(5) P7d(15) 13.B6h(14) P9d(32) +# +1.P7f P8d 2.P2f(3) P8e(2) 3.B7g P3d 4.S8h G3b(1) 5.G7h(1) Bx7g+(8) +6.Sx7g S4b 7.S3h S7b(1) 8.P4f(2) K4a(17) 9.S4g(1) S8c(3) 10.P3f(2) +S8d(1) 11.P9f(6) P9d(5) 12.G5h(2) K3a(9) 13.N3g(2) G5b(8) 14.P4e(20) +# +1.P7f P8d(2) 2.S6h P3d(1) 3.P6f S6b(2) 4.P5f P5d(1) 5.S4h S4b 6.G4i-5h +G3b(1) 7.G6g(1) K4a(1) 8.G7h(3) G5b(1) 9.K6i S3c 10.S7g(1) B3a(1) 11.B7i +P4d(5) 12.P3f(2) P7d(3) 13.B6h(26) G5b-4c(18) 14.K7i(4) P8e(3) +# +1.P7f P8d 2.S6h(6) P3d 3.P6f(1) S6b 4.P5f(2) P5d 5.G4i-5h(1) S4b(1) +6.S4h(2) G3b(2) 7.G6g(4) K4a 8.G7h(4) G5b(6) 9.K6i(3) S3c(4) 10.S7g(3) +B3a(2) 11.B7i(6) P4d 12.P3f(3) G5b-4c(3) 13.B6h(1) P7d(26) 14.K7i(2) +# +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f P1d 8.S3h +P3d 9.K5h P9d 10.P3f B4d 11.P3e Bx3e 12.R5f S4b 13.P7f B4d 14.Bx4d Px4d 15.N7g +# +1.P7f P8d 2.S6h P3d 3.P6f S6b 4.P5f P6d 5.G7h S6c 6.G5h P6e 7.S7g Px6f 8.Sx6f +P8e 9.G5h-6g P8f 10.Px8f Rx8f 11.S7e R8b 12.P'8d P'6d 13.Bx2b+ Sx2b 14.G7h-7g +# +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2h P8f 7.Px8f Rx8f +8.P'8g R8d 9.S3h S7b 10.P7f P9d 11.P9f P1d 12.P4f R7d 13.G7g R2d 14.P'2e R8d +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.S4h S4b 5.P5f P5d 6.G4i-5h G3b 7.P6f P6d 8.G6g +S6c 9.P2f P5e 10.Px5e Bx5e 11.P2e B2b 12.G7h K4a 13.K6i P7d 14.S5g S5d 15.P2d +# +1.P7f(1) P8d(1) 2.P5f(3) P8e(5) 3.B7g P5d 4.R8h(1) P3d(2) 5.S6h S6b 6.K4h +P7d(20) 7.P6f(9) K4b(2) 8.K3h K3b 9.K2h G6a-5b 10.G6i-5h(6) S5c 11.S5g(13) +B3c(5) 12.L1h(3) K2b 13.K1i S3b 14.S2h P1d(3) 15.G3i(1) P2d 16.G6g(24) +# +1.P7f P3d(1) 2.P2f P4d 3.P2e B3c 4.S4h S4b(5) 5.P5f(1) R5b(1) 6.K6h K6b +7.K7h K7b(1) 8.G4i-5h K8b(2) 9.P3f(10) S4c(5) 10.P4f(4) G3b(4) 11.S5g(2) +L9b(2) 12.N3g(44) R5a(12) 13.P9f(7) P5d(5) 14.P9e(12) K9a 15.B6f(3) S8b(1) +# +1.P7f(1) P8d(1) 2.S6h(6) P3d(1) 3.P6f S6b 4.G4i-5h S4b(1) 5.S4h P5d 6.G6g(1) +G3b(1) 7.P5f(2) K4a 8.S7g P7d 9.G7h(2) G5b 10.B7i S3c 11.K6i(3) B3a +12.P3f(6) P4d(10) 13.B6h(12) G5b-4c(13) 14.K7i B6d 15.N3g(5) K3a(1) 16.K8h +# +1.P7f P3d(1) 2.P2f P4d 3.S4h S4b(3) 4.P5f P5d 5.K6h(3) S6b(4) 6.K7h(2) +P7d(1) 7.S6h(2) R7b(7) 8.G4i-5h(6) P7e(6) 9.Px7e(2) Rx7e 10.S7g N7c(5) +11.P'7f(7) R7d 12.P6f N8e(4) 13.S8f(11) Rx7f(7) 14.K6g(8) R7b(1) 15.Sx8e +# +1.P7f P8d(1) 2.P5f(2) P3d(8) 3.P6f(2) S6b 4.S6h P5d 5.R5h(1) K4b(2) 6.K4h +K3b 7.K3h G6a-5b(6) 8.K2h(1) S5c(2) 9.L1h(2) B3c 10.K1i K2b 11.S5g P4d(1) +12.S4f(29) G4c(2) 13.P5e(1) P4e(14) 14.Sx4e(1) Px5e 15.S3f(6) S3b(6) +# +1.P7f P3d 2.P2f P4d 3.S4h S4b(5) 4.P5f P5d 5.G4i-5h G6a-5b(3) 6.S6h(2) S6b +7.S7g S3c 8.K6h K4b 9.K7h K3b 10.P6f B3a 11.G6g P7d 12.B7i S7c 13.S5g(1) G4c +# +1.P2f P8d(1) 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f(2) +P3d(3) 8.P1e(3) P6d(1) 9.R3f(22) G3c(3) 10.S3h(25) S6c(5) 11.P7f(1) P8f(2) +12.Px8f Rx8f 13.P'8g(2) R8b(10) 14.R2f S5d(3) 15.P3f G3b(1) 16.N3g B4d(3) +# +1.P7f(1) P8d 2.S6h P3d 3.P6f S6b 4.G4i-5h(1) S4b 5.S4h G3b 6.G6g K4a 7.G7h +P5d 8.K6i G5b 9.P5f(1) P4d(1) 10.S7g S3c 11.B7i B3a 12.P3f P7d(10) +# +1.P2f P8d(1) 2.P2e(1) P8e 3.G7h(2) G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b +7.P9f(1) P1d(1) 8.P7f P8f(5) 9.Px8f Rx8f 10.N7g S4b(1) 11.K4h(1) P9d(3) +12.S3h(1) K4a(2) 13.B9g(13) R8b(6) 14.P7e P3d(2) 15.R8f(5) P'8e(13) +# +1.P7f P8d 2.P2f(1) P8e(1) 3.B7g P3d(1) 4.S8h G3b(3) 5.G7h Bx7g+ 6.Sx7g S4b +7.S3h(1) S7b(2) 8.P4f(1) P6d(1) 9.S4g S6c 10.P6f(3) P4d(2) 11.G5h(3) G5b(3) +12.K6h(1) K4a(3) 13.K7i(1) K3a(2) 14.P3f(1) P7d(5) 15.S5f(4) S5d(1) 16.P9f +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.P5f(1) P5d 5.S4h S4b 6.G4i-5h(2) G3b +7.P6f K4a 8.G6g P7d(5) 9.G7h(10) G5b 10.K6i(1) S3c(3) 11.B7i(6) B3a(1) +12.P3f(1) P4d(1) 13.B6h(26) G5b-4c(13) 14.K7i(3) B6d(8) 15.N3g(2) K3a +# +1.P7f P8d(1) 2.S6h(2) P3d(1) 3.S7g S6b(1) 4.S4h P5d(1) 5.P5f S4b 6.G4i-5h(6) +G3b(2) 7.P6f(2) K4a(3) 8.G6g P7d(2) 9.G7h(5) G5b(2) 10.K6i S3c 11.B7i(2) +B3a(7) 12.P3f(10) P4d(4) 13.S3g(9) B6d(17) 14.B6h(10) G5b-4c(8) 15.K7i(4) +# +1.P7f P8d 2.S6h(2) P3d(1) 3.S7g S6b 4.P5f(1) P5d 5.S4h(1) S4b 6.G4i-5h(1) +G3b(2) 7.P6f(1) K4a 8.G6g P7d(5) 9.G7h(5) G5b 10.K6i(2) S3c(3) 11.B7i(3) B3a +12.P3f(1) P4d(6) 13.B6h(5) G5b-4c(14) 14.K7i(1) S7c(7) 15.K8h(22) P9d(8) +# +1.P7f P8d(1) 2.P2f P8e(1) 3.B7g P3d(1) 4.S8h G3b 5.G7h Bx7g+(4) 6.Sx7g S4b +7.S3h S7b(2) 8.P4f P6d(1) 9.S4g S6c 10.P6f P4d(2) 11.G5h(1) G5b 12.K6h K4a +# +1.P7f P8d 2.S6h(2) P3d(1) 3.S7g S6b(1) 4.P5f(1) P5d 5.S4h S4b(1) 6.G4i-5h G3b +7.P6f K4a 8.G6g P7d(2) 9.G7h(6) G5b(6) 10.K6i(2) S3c(6) 11.B7i(3) B3a(1) +12.P3f(7) P4d(1) 13.B6h(11) P9d(13) 14.K7i(49) P9e(11) 15.K8h(11) L9c(21) +# +1.P7f P8d 2.S6h(1) P3d 3.S7g S6b(1) 4.S4h P5d 5.P5f S4b(1) 6.G4i-5h G3b(1) +7.P6f K4a(1) 8.G6g P7d(4) 9.G7h(20) G5b(8) 10.K6i S3c 11.B7i B3a(2) 12.P3f +P4d(3) 13.B6h(4) G5b-4c(20) 14.K7i(2) B6d(4) 15.N3g(2) K3a(4) 16.K8h(9) +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.S4h P5d 5.P5f S4b 6.G4i-5h G3b +7.P6f K4a 8.G6g P7d 9.G7h S3c 10.K6i G5b 11.B7i B3a 12.P3f P4d 13.S3g B6d +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f G3b 5.S4h K4a 6.G4i-5h G5b +7.P6f P6d 8.P2f S4b 9.G6g P7d 10.G7h S6c 11.K6i N7c 12.P2e S3c +13.B7i P8e 14.P3f P5d 15.S3g +# +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S4b +7.S3h S7b 8.P4f P6d 9.S4g S6c 10.G5h G5b 11.K6h K4a 12.S5f S5d +13.P6f P4d 14.P3f P7d 15.K7i K3a 16.N3g P1d 17.P1f G5b-4c +# +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S4b +7.S3h S7b 8.P4f S3c 9.S4g K4b 10.G5h S8c 11.P6f S8d 12.P9f P7d +# +1.P7f P3d 2.P2f P4d 3.P2e B3c 4.S4h S3b 5.P5f R4b +6.K6h K6b 7.K7h K7b 8.G4i-5h G4a-5b 9.P9f P9d 10.S5g K8b +11.P8f S4c 12.K8g S7b 13.S7h P6d 14.S6f G6c +# +1.P2f(1) P8d 2.P2e(1) P8e 3.G7h G3b 4.P2d(1) Px2d 5.Rx2d P'2c 6.R2f S7b(3) +7.S3h(2) P6d(12) 8.P1f(8) P1d(17) 9.P7f(3) P8f(7) 10.Px8f(2) Rx8f 11.P'8g(15) +R8b(20) 12.P4f(5) S6c(3) 13.S4g(2) S5d(4) 14.S5f(3) P3d 15.G4h(21) G5b(2) +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.P5f(1) P5d(1) 5.S4h S4b(1) 6.G4i-5h(1) +G3b(2) 7.P6f(1) K4a(1) 8.G6g P7d(7) 9.G7h(10) S6b-5c(28) 10.P2f(13) P5e(3) +11.Px5e(11) Bx5e(1) 12.P2e S5d(1) 13.P2d(7) Px2d(4) 14.Rx2d P'2c(1) 15.R2h +# +1.P7f P8d(1) 2.S6h P3d 3.P6f(1) S6b(1) 4.P5f(2) P5d(1) 5.S4h(1) S4b(1) +6.G4i-5h(2) G3b(5) 7.G6g(1) K4a(1) 8.G7h(5) G5b(15) 9.K6i(1) S3c 10.S7g(1) B3a +11.B7i(1) P4d 12.P3f(2) P7d(5) 13.B6h(29) G5b-4c(12) 14.K7i(8) B6d(3) +# +1.P7f P8d 2.S6h(1) P3d 3.P6f S6b(3) 4.P5f P5d(1) 5.S4h(1) S4b(1) 6.G4i-5h(2) +G3b 7.G6g(1) K4a(1) 8.G7h G5b(4) 9.K6i(1) S3c(3) 10.S7g(1) B3a(1) 11.B7i(1) +P4d(5) 12.P3f G5b-4c(3) 13.S3g(39) P8e(28) 14.P3e(97) Px3e(7) 15.Bx3e P4e(1) +# +1.P7f(1) P8d(1) 2.S6h(3) P3d 3.P6f(1) S6b 4.P5f P5d 5.S4h(2) S4b 6.G4i-5h(2) +G3b 7.G6g(3) K4a 8.G7h(4) G5b(3) 9.K6i(4) S3c(1) 10.S7g(1) B3a(2) 11.B7i(2) +P4d 12.P3f(2) G5b-4c(9) 13.B6h(3) P7d(19) 14.K7i(2) B6d(6) 15.S3g(25) K3a(36) +# +1.P7f P8d(2) 2.P2f G3b(2) 3.G7h(2) P8e(5) 4.B7g(2) P3d 5.S8h Bx7g+(3) 6.Sx7g +S4b(1) 7.S3h S7b(2) 8.P4f(2) P6d(15) 9.S4g(8) S6c 10.P6f(9) P1d(26) 11.P1f(11) +P9d(3) 12.P9f(5) S5d 13.S5f(1) P4d(4) 14.G5h(35) G5b(8) 15.K6h(10) K4a(2) +# +1.P7f(1) P8d 2.S6h(2) P3d 3.P6f S6b(1) 4.P5f(1) P5d 5.S4h(2) S4b 6.G4i-5h(4) +G3b 7.G6g(1) K4a(1) 8.G7h(3) G5b(1) 9.K6i(1) S3c(2) 10.S7g(2) B3a(2) 11.B7i(1) +P4d 12.P3f(2) G5b-4c(9) 13.B6h(3) B6d(26) 14.S3g(11) P7d(3) 15.K7i(5) K3a(1) +# +1.P7f(2) P8d(1) 2.G7h(5) G3b(11) 3.B7g(15) P3d(5) 4.S6h(3) S6b(2) 5.S4h(4) +P6d(4) 6.P4f(1) S6c(7) 7.S4g(1) S5d(10) 8.S5f(4) G5b(9) 9.G5h(9) K4a(2) +10.K6i(5) Bx7g+(18) 11.Sx7g(1) S4b 12.P6f(10) P4d(4) 13.K7i(1) K3a(3) +# +# 31-st Oi Title Match, 1-st game, July 12-th and 13-th 1990. +# Black: Tanigawa, Oi; White: Sato, 5-dan +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f P1d 8.S3h +P6d 9.P7f P8f 10.Px8f Rx8f 11.P'8g R8b 12.P3f P3d 13.S3g S6c 14.P3e Px3e 15.S4f +S5d 16.K5h Bx8h+ 17.Sx8h S2b 18.P'3d G5b 19.G3h P4d 20.P7e K4b 21.Sx3e S4c +22.N7g P'3c 23.Px3c+ Sx3c 24.P7d Px7d 25.P'7b Rx7b 26.B'8c R7c 27.B6a+ G5a +28.N8e Gx6a 29.Nx7c+ Nx7c 30.R'8a S5b 31.Rx9a+ N6e 32.G4h B'3i 33.G6h P'3d +34.S4f N'7f 35.G6i Nx8h+ 36.L'6c +N7h 37.Gx7h S'6i 38.Kx6i Bx4h+ 39.R2h B'5h +40.K7i +B5i 41.Lx6a+ +B6i 0-1 +# +# 31-st Oi Title Match, 2-nd game, July 23-rd and 24-th 1990. +# Black: Sato, 5-dan; White: Tanigawa, Oi +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.P6f K4a 8.G6g +G5b 9.B7i S3c 10.P3f B3a 11.K6h P4d 12.K7h G5b-4c 13.K8h B6d 14.S3g P8e 15.G7h +P7d 16.S4f K3a 17.N3g S5c 18.P1f P1d 19.P2f K2b 20.R5h B7c 21.P5e Px5e 22.Sx5e +P'5d 23.S4f S6d 24.R3h S2d 25.L1g S5e 26.S5g N3c 27.P4f P3e 28.P2e Nx2e 29.Nx2e +Sx2e 30.Px3e S2f 31.P6e Sx1g+ 32.P'5f +S2g 33.R3i N'8f 34.Px5e Nx7h+ 35.Kx7h +P'3f 36.Px5d P3g+ 37.R5i L'8c 38.S5g-6h +P4h 39.R5g P8f 40.Px8f Lx8f 41.Sx8f +Rx8f 42.P'8g S'6i 43.K8h R8b 44.P5c+ G'4g 45.+Px4c Gx5g 46.+Px3b Kx3b 47.G'7g ++P5h 48.Sx5g R'3h 49.S6h +Px6h 50.Gx6h Bx4f 51.P'5h Sx5h+ 52.L'3d K4c 53.L3c+ +K5c 54.S'4g +Sx6h 55.Sx3h +Sx7i 56.R'5f S'5e 57.Rx4f Sx4f 58.B'7a K5d 59.Bx8b+ +G'7h 60.Gx7h +Sx7h 61.Kx7h B'5f 62.K7g B6g+ 0-1 +# +# 31-st Oi Title Match, 3-rd game, August 9-th and 10-th 1990. +# Black: Tanigawa, Oi; White: Sato, 5-dan +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S2b 7.S3h S7b 8.P4f +S3c 9.S4g P6d 10.G5h S6c 11.P3f P1d 12.P1f P7d 13.K6h N7c 14.P6f G6b 15.P2e R8a +16.N3g K4b 17.S5f K3a 18.K7i S5d 19.K8h P6e 20.P3e P4d 21.P4e B'6d 22.R2g Px6f +23.P2d Px2d 24.Px3d Sx3d 25.Px4d P8f 26.Sx8f P'3f 27.Rx2d S2c 28.Rx2c+ Gx2c +29.P4c+ Sx4c 30.B'4e R'2h 31.Bx8a+ Rx5h+ 32.+Bx3f +Rx5g 33.P'4d G'6h +34.R'2h Gx7h 35.Kx7h +Rx5f 36.G'4b Kx4b 37.Px4c+ K5a 38.S'5b Gx5b 39.+Px5b Kx5b +40.S'4c 1-0 +# +# 31-st Oi Title Match, 4-th game, August 23-rd and 24-th 1990. +# Black: Sato, 5-dan; White: Tanigawa, Oi +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.P6f K4a 8.G6g +P6d 9.P2f S6c 10.P2e P5e 11.Px5e Bx5e 12.G7h P7d 13.K6i S5d 14.P2d Px2d 15.Rx2d +P'2c 16.R2h B2b 17.S5g S5c 18.S7g-6h G5b 19.K7i G6c 20.P3f P8e 21.B7g N7c +22.P'5f P1d 23.P9f P9d 24.S4f S4d 25.P1f P'5e 26.Px5e S4dx5e 27.P'5f Sx4f +28.Px4f P8f 29.Px8f P'8e 30.Px8e Nx8e 31.B8f P6e 32.P'8c R9b 33.S5g Px6f +34.Gx6f P'6e 35.P'6d G6b 36.G5e Sx5e 37.Px5e Bx5e 38.P8b+ Rx8b 39.S'7a S'7g +40.Nx7g Nx7g+ 41.Bx7g Bx7g+ 42.Gx7g G'8i 43.K6i R8h+ 44.Rx8h Gx8h 45.K5h R'2h +46.N'4h P'5f 47.Sx6b+ Px5g+ 48.Kx5g K3a 49.S'4a B'6h 50.K5f Bx7g+ 51.Sx3b+ +Kx3b 52.S'4a Kx4a 53.G'4b 1-0 +# +# 31-st Oi Title Match, 5-th game, August 30-th and 31-st 1990. +# Black: Tanigawa, Oi; White: Sato, 5-dan +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S4b 7.S3h S7b +8.P4f P6d 9.S4g S6c 10.G5h P1d 11.P1f P9d 12.P9f G5b 13.P3f K4a 14.S5f S5d +15.K6h P4d 16.P6f P7d 17.K7i K3a 18.N3g N7c 19.P2e P6e 20.Px6e P7e 21.P2d +Px2d 22.P'2e Px2e 23.Px7e Nx6e 24.Sx6e Sx6e 25.Rx2e B'4c 26.P'2b P'2d +27.Px2a+ Kx2a 28.Rx2d P'2c 29.R2h P'7f 30.S6h S6f 31.N'5f P8f 32.Px8f P'8h +33.Nx4d Px8i+ 34.K6i S'7g 35.Nx3b+ Bx3b 36.N'4d Sx7h+ 37.K5i N'2d 38.Nx3b+ +Kx3b 39.K4i N'4d 40.S5i N4dx3f 41.R2e +S6i 42.P'3c Sx3c 43.N4e N'4a 44.P'3g ++Sx5i 45.Gx5i P'4d 46.Px3f Px4e 47.B'6e S'5d 48.Bx5d Px5d 49.B'6d B'4g +50.G4h Bx3f+ 51.G'3a K2b 52.Gx4a N'5c 53.S'3a K2a 54.P'2b K3b 55.Bx8b+ +Bx2e +56.N'4d Sx4d 57.R'4b K3c 58.Rx4d+ Kx4d 59.N'5f 1-0 +# +# 31-st Oi Title Match, 6-th game, September 10-th and 11-th 1990. +# Black: Sato, 5-dan; White: Tanigawa, Oi +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.P6f K4a 8.G6g +G5b 9.B7i S6b-5c 10.P2f P6d 11.P2e R6b 12.G7h P6e 13.Px6e Rx6e 14.P'6f R6a +15.P3f S6d 16.P2d Px2d 17.Bx2d P'2c 18.B4f P4d 19.B3g P4e 20.K6i K3a 21.S5g S4c +22.K7i P9d 23.P9f G5b-4b 24.P1f P5e 25.P4f Px5f 26.Sx5f Px4f 27.Bx4f P'5e 28.S4g +P'4e 29.B6h P'6e 30.P'2d Px2d 31.P'2e Px2e 32.P'2d B4d 33.Px6e Sx6e 34.P'6f +S6e-5d 35.Rx2e P'2b 36.N3g N9c 37.R2h N8e 38.P'4f Nx7g+ 39.G6gx7g Px4f 40.Sx4f +S'5f 41.P'4e B5c 42.K8h P'6e 43.Px6e P'6f 44.Gx6f S5dx6e 45.Gx6e Rx6e 46.P'6f +R6c 47.Sx5e G'6g 48.P'5d Gx7h 49.Kx7h G'6g 50.K8h Gx6h 51.Px5c+ Rx5c 52.P'5d +Sx5d 53.S'4d Sx5e 54.Sx5c+ B'7i 55.K9h Gx5c 56.B'8f P'5b 57.R'6a P'4a 58.Bx6h +Bx6h+ 59.Rx6h B'4f 60.G'5a K4b 61.Gx4a K3c 62.N'2e Kx2d 63.G'1e K2c 64.P'2d +K1b 65.G4b Bx6h+ 66.Rx2a+ 1-0 +# +# 31-st Oi Title Match, 7-th game, September 20-th and 21-st 1990. +# Black: Sato, 5-dan; White: Tanigawa, Oi +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f G3b 5.S4h K4a 6.G4i-5h P6d 7.G7h B3c 8.K6i +S2b 9.P6f S6c 10.G5h-6g B5a 11.P3f P7d 12.B7i B7c 13.S3g S3c 14.S4f P4d 15.N3g +P8e 16.P2f S5d 17.P5e S4c 18.B6h G5b 19.K7i B8d 20.R3h S2d 21.P1f P1d 22.K8h N7c +23.N2e P6e 24.Px6e Nx6e 25.S6f P'6d 26.P9f P9d 27.L1g G5b-4b 28.R1h K3a 29.P3e +Px3e 30.P1e Px1e 31.P'1c Lx1c 32.Sx3e Sx2e 33.Px2e P'3d 34.S4f P9e 35.Px9e P'9g +36.Lx9g P4e 37.Sx4e Bx6f 38.Gx6f S'5g 39.G6f-6g Sx6h+ 40.Rx6h P'9f 41.Lx9f N'8d +42.K9h Nx9f 43.B'7c R9b 44.S'9g P7e 45.Sx9f Px7f 46.Bx6d+ P7g+ 47.Nx7g Nx7g+ +48.G6gx7g P'7f 49.Gx7f N'8d 50.+B7c Rx9e 51.R6a+ P'4a 52.Sx9e Lx9e 53.K8i Nx7f +54.+Bx9e S'9g 55.S'7g B'5g 56.P'9h L'8h 57.Sx8h Sx8h+ 58.Gx8h S'9g 0-1 +# +# 32-nd Oi Title Match, 1-st game, 11-th and 12-th July 1991. +# Black: Tanigawa Koji, Oi; White: Nakada Hiyoki, challenger. +1.P7f P8d 2.S6h(3) P3d 3.S7g S6b 4.S4h(1) S4b 5.P5f P5d 6.G4i-5h G3b(2) +7.P6f(2) K4a 8.G6g P7d(5) 9.G7h(11) G5b(2) 10.K6i S3c(3) 11.B7i(5) B3a(1) +12.B6h(7) P9d(26) 13.P3f(12) P9e(38) 14.K7i(55) N7c(9) 15.K8h(21) L9c(42) +16.P3e(22) Px3e(27) 17.Bx3e S4d(35) 18.B4f(27) S4e(6) 19.B6h(6) R9b 20.S8f(8) +N8e(8) 21.R3h(42) P'3c(6) 22.S5g(25) Nx9g+(21) 23.Sx9g(3) P9f 24.S8f(38) +P8e(80) 25.N'8d(2) R9a 26.P'9b R7a 27.S9e(6) S7c(40) 28.R3e(17) Lx9e(5) +29.Bx9e S'4d(1) 30.R3h(18) P9g+(4) 31.Lx9g P'9d 32.B5i Sx8d 33.L'4f Sx4f(9) +34.Px4f P7e(2) 35.P4e(9) S5c(2) 36.B3g(9) P6d(5) 37.B2f Px7f(1) 38.P5e(1) +P8f(15) 39.Px8f(3) P'8g 40.K7i R7c 41.Px5d(26) Sx5d(14) 42.P'5c(3) Bx5c +43.P'7d R8c(1) 44.Bx5c+ Rx5c 45.B'2f R8c(4) 46.B7a+(4) N'5e 47.G6g-6h(3) +N4g+(3) 48.R1h +Nx5g(5) 49.Gx5g L'7g 50.Nx7g(6) Px7g+ 51.Gx7g P'5f(14) +52.Gx5f(3) B'4g 53.G5g S'8h 54.Resigns(2) +# +# 32-nd Oi Title Match, 2-nd game, 22-nd and 23-rd July 1991. +# Black: Nakada Hiyoki, challenger; White: Tanigawa Koji, Oi. +1.P7f P8d 2.S6h(1) P3d 3.S7g S6b(1) 4.S4h S4b 5.P5f P5d(3) 6.G4i-5h(1) G3b +7.P6f(1) K4a(1) 8.G6g G5b(1) 9.B7i(8) S6b-5c(55) 10.G7h(26) P6d(5) 11.P2f(7) +R6b(4) 12.P2e(1) P6e(1) 13.Px6e(1) Rx6e 14.P'6f R6a 15.K6i(16) S6d(14) +16.P2d(4) Px2d 17.Bx2d P'2c(3) 18.B4f P5e(39) 19.S5g(34) S4b-5c(15) 20.P3f(11) +S5d(6) 21.N3g(50) P4d(38) 22.K7i(14) P1d(41) 23.K8h(58) P4e(31) 24.Bx5e(1) +S6dx5e 25.Px5e Bx5e 26.P4f P'5c 27.P3e(84) P7d(66) 28.G5f(26) B7c(30) +29.P'5e(7) Sx5e(16) 30.Gx5e Bx5e 31.P'5d(22) B'3i(23) 32.Nx4e(44) Px5d(8) +33.P'5c(10) G5a 34.R2g(16) K3a(11) 35.Px3d(1) G'3f 36.S5f B3ix6f+ 37.Sx5e(11) ++Bx5e 38.P'2b(13) Gx2g(5) 39.Px2a+ Kx2a 40.S'3c(6) R'3h(2) 41.Sx3b+ K1b +42.G'4h S'7i(13) 43.Kx7i(1) +Bx4f(4) 44.S'5g(1) +Bx5g(10) 45.Gx5g S'6i 46.N'5h +Sx7h+(20) 47.Kx7h G'6g 48.Gx6g(1) Rx5h+ 49.K7i Resigns +# +# 32-nd Oi Title Match, 3-rd game, 6-th and 7-th August 1991. +# Black: Tanigawa Koji, Oi; White: Nakada Hiyoki, challenger. +1.P7f P8d(1) 2.P2f P8e(1) 3.B7g P3d 4.S8h G3b(1) 5.G7h Bx7g+(1) 6.Sx7g S4b +7.S3h S7b 8.P4f P6d(11) 9.S4g S6c 10.P6f P4d(3) 11.G5h G5b 12.K6h(1) K4a(1) +13.K7i K3a 14.P3f(2) P7d(3) 15.S5f(1) S5d 16.P9f(17) P9d(19) 17.N3g(13) +P1d(16) 18.P1f(4) S3c(68) 19.R4h(29) P3e(43) 20.Px3e(37) S2d 21.P3d S3e(16) +22.G4g(10) Sx2f(35) 23.R2h(58) S3e(29) 24.N2e(36) G5b-4c(66) 25.P1e(7) P2d(3) +26.P3c+(1) Nx3c 27.Nx3c+ G4cx3c 28.Px1d P'1b(4) 29.P'3d(25) Gx3d(62) +30.B'7a(8) R5b 31.P'3f Sx4f 32.Gx4f B'3g 33.G3e(23) Gx3e 34.S'6a R9b(12) +35.Rx2d P'2c(5) 36.R2i(19) G3d(3) 37.Bx5c+ N'4b 38.P'4c(13) Gx4c(3) +39.+Bx4c(2) Sx4c 40.Rx2c+ G'3b(3) 41.G'2b Gx2b 42.+Rx4c G'3c(9) 43.+R8c(1) +K3b(1) 44.P'4c(8) K2c(19) 45.Px4b+(1) Rx4b 46.S'3a(4) R3b(1) 47.Sx2b+ Rx2b +48.P'2e(1) Gx2e(2) 49.N'3e(3) K2d(2) 50.+Rx3c Kx3c 51.G'4c Resigns +# +# 32-nd Oi Title Match, 4-th game, 19-th and 20-th August 1991. +# Black: Nakada Hiyoki, challenger; White: Tanigawa Koji, Oi. +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.S4h S4b 5.P5f P5d 6.G4i-5h G3b 7.P6f K4a +8.G6g P7d 9.G7h(5) G5b(5) 10.K6i(1) S3c(3) 11.B7i(2) B3a(1) 12.P3f P4d(18) +13.B6h(41) G5b-4c(3) 14.K7i B6d(7) 15.N3g(5) K3a(2) 16.K8h(1) P8e(7) 17.P2f(3) +K2b(5) 18.R3h(2) S5c(7) 19.P1f(45) P1d(21) 20.P9f(44) P9d(13) 21.S5g B7c(18) +22.S4f(1) S2d(17) 23.L1h(6) P9e(24) 24.Px9e(16) Lx9e 25.P'9g(16) S4b(25) +26.N2e(8) N3c(17) 27.P5e(57) Px5e(40) 28.P3e(1) Px3e 29.P1e Px1e(1) 30.Sx3e +Sx3e 31.Rx3e(24) P'3d(5) 32.R3i Nx2e(15) 33.Px2e P5f 34.Lx1e(29) Lx1e(18) +35.N'1d(1) K3c 36.B1c+(1) S5c(1) 37.S'4a(81) B2h+(16) 38.R5i(2) L'5d(5) +39.P'5b(25) G4c-4b(42) 40.P5a+(1) P5g+(11) 41.Gx5g(1) S'4h 42.Sx3b+(24) Gx3b +43.R5h(3) Lx5g+(4) 44.P'5d Sx5d 45.Rx4h(1) +Lx4h 46.G'5c P3e(3) 47.+Bx3e(11) +G'3d 48.+B1c(4) P'1b(13) 49.S'2b(4) Gx2b 50.Nx2b+ Px1c 51.G'3b Rx3b 52.+Nx3b +Kx3b 53.R'5b K2a 54.Gx5d P'3b(3) 55.G4c(2) G'3c 56.S'4a(2) S'3a(1) 57.Gx3c(1) +Gx3c 58.P'3d B'4e(7) 59.Px3c+(4) Bx7h+(1) 60.Kx7h G'7i 61.Resigns +# +# 32-nd Oi Title Match, 5-th game, 28-th and 29-th August 1991. +# Black: Tanigawa Koji, Oi; White: Nakada Hiyoki, challenger. +1.P7f P8d(1) 2.P2f P8e 3.B7g P3d 4.S8h G3b(1) 5.G7h Bx7g+(1) 6.Sx7g S4b 7.S3h +S7b 8.P4f P6d(3) 9.S4g(1) S6c 10.P6f(3) P4d(1) 11.G5h(2) G5b(1) 12.K6h(2) +K4a(1) 13.K7i K3a(1) 14.P3f(1) P7d(10) 15.S5f(13) S5d(4) 16.P9f(11) P9d(7) +17.P1f(18) P1d(1) 18.N3g(3) N7c(33) 19.P2e(19) S3c(5) 20.P4e(46) Px4e(2) +21.P3e P6e(93) 22.Px6e(12) P7e(67) 23.P2d(90) Px2d(2) 24.B'6f B'4d(45) +25.Nx4e(9) Bx6f(12) 26.Sx6f S4d(5) 27.P'2b(7) Kx2b(17) 28.Px3d(11) B'4f(12) +29.R2i(64) P8f(26) 30.Px8f S5dx4e(17) 31.B'2f Sx5f(33) 32.Bx4d(1) P'3c +33.P'4g(13) S'3h(1) 34.Px4f(10) Sx2i+ 35.Px5f R'3i(9) 36.K6h(3) Rx8f(12) +37.P'2c(10) Gx2c(2) 38.P'8g P'6g(3) 39.Kx6g(1) R8d(1) 40.B5e(15) R8dx3d(6) +41.B'4a(5) R3d-3g+(4) 42.S5g G4b(5) 43.S'3a Kx3a 44.Bx2c+ S'2b 45.+B4e +Nx6e(3) 46.P'2c Nx5g+(8) 47.Gx5g(3) S'3d 48.N'3e(13) S2bx2c(5) 49.Nx2c+(22) +Sx4e 50.Px4e R6i+(3) 51.G'6h(2) B'4i 52.K7g Bx7f+(5) 53.K8h +Bx8g 54.Gx8g(7) ++Rx6h 55.K9g +R3gx5g 56.S'2b K4a 57.B'8e P'6c(3) 58.S'7g(15) N'9c(1) +59.Bx9d(3) P'8f(2) 60.Gx8f(1) G'7h(2) 61.G8g(8) P'8e(1) 62.P'8f(5) Gx7g +63.Nx7g(1) S'7h 64.G'8h(2) Sx8g+ 65.Gx8g Px8f 66.Kx8f G'8d 67.S'4c(3) Gx4c +68.S'3b(2) K5a 69.B7c+ Resigns +# +# 32-nd Oi Title Match, 6-th game, 10-th and 11-th September 1991. +# Black: Nakada Hiyoki, challenger; White: Tanigawa Koji, Oi. +1.P7f P8d(1) 2.S6h P3d 3.S7g S6b(1) 4.S4h(1) S4b 5.P5f P5d 6.G4i-5h G3b(2) +7.P6f K4a(1) 8.G6g P7d(7) 9.G7h(2) G5b(1) 10.K6i(1) S3c 11.B7i B3a(3) 12.P3f +P4d 13.B6h(10) G5b-4c(10) 14.K7i(1) B6d(12) 15.N3g(7) K3a(5) 16.K8h(1) K2b(1) +17.P2f(1) P8e(9) 18.R3h(11) S5c(12) 19.P1f(3) P1d(8) 20.L1g(12) P5e(28) +21.S5g(69) Px5f(38) 22.Sx5f(4) S5d(11) 23.P'5e(30) Sx5e(72) 24.S6e B3a +25.Sx7d(50) P'5f(31) 26.Sx6c+(75) P8f(26) 27.Sx8f(12) R8c(22) 28.+S5b P'6e(1) +29.Px6e N7c(9) 30.P'5h(48) R8b(49) 31.+S4a(9) B5c 32.P1e Px1e(4) 33.P'1b(3) +Lx1b 34.P'1c Lx1c 35.N2e(9) S2d 36.Nx1c+(8) Sx1c 37.R1h(1) P'6f(15) +38.Bx1c+(10) Nx1c(7) 39.G6g-6h(3) P4e(7) 40.Lx1e(1) K3c(1) 41.Lx1c+ N'9d(4) +42.L'4f(17) Nx8f(19) 43.Px8f(35) P'1g(11) 44.Lx4e(3) G4d(4) 45.Lx4d(1) Kx4d +46.N'3g(14) Bx8f(8) 47.P'8g(3) Bx6h+ 48.Gx6h Rx8g+ 49.Kx8g P'8f 50.Kx8f B'9e +51.K8g L'8f 52.Resigns +# +# 33-rd Oi Title Match, 1-st game, 10-th and 11-th July 1992. +# Black: Tanigawa Koji, Oi; White: Gouda Masataka, challenger. +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g(1) S6b 4.P5f(1) P5d 5.S4h S4b 6.G4i-5h G3b +7.P6f(1) K4a 8.G6g(2) G5b(42) 9.P2f(15) P7d(6) 10.B7i(17) P6d(17) 11.G7h(3) +S6b-5c(3) 12.P2e(4) G6c(80) 13.K6i(17) N7c(4) 14.P3f(65) P5e(50) +15.Px5e(36) Bx5e 16.S3g S5d(52) 17.P2d(13) Px2d(3) 18.Bx2d P'2c 19.B1e +N8e(22) 20.S6h(62) P6e(1) 21.S4f(7) B3c(72) 22.Bx3c+(1) Nx3c 23.Px6e R5b +24.P8f(23) Sx6e(21) 25.Px8e(3) P'6f 26.G6g-7g B'5f(6) 27.B'5h(14) N4e(25) +28.P'5g(8) Bx7h+ 29.Gx7h P'5f 30.Px5f Sx5f 31.N'5e(55) G6d(23) 32.B'7c(3) +Gx5e(2) 33.Bx5e+ Rx5e(6) 34.Sx5e N5g+ 35.P'5c(21) P'5a 36.R'2a S3a(14) +37.Sx5g(22) Sx5g= 38.S4f B'3i(3) 39.Sx5g(2) Bx2h+(2) 40.S'6c R'3i(3) 41.K6h +G'4b 42.Sx6f(16) Rx8i+(2) 43.G'6b(12) G2b(2) 44.P5b+(2) Px5b 45.Sx5b+ +Gx5b(6) 46.Gx5b Kx5b 47.Rx3a+ S'5i(4) 48.K6g(2) S'5f 49.Resigns +# +# 33-rd Oi Title Match, 2-nd game, 21-st and 22-nd July 1992. +# Black: Gouda Masataka, challenger; White: Tanigawa Koji, Oi. +1.P7f P3d(2) 2.P2f P4d 3.S4h(3) S3b(5) 4.P5f R4b 5.K6h K6b 6.K7h K7b +7.G4i-5h K8b(1) 8.P9f P9d(28) 9.S6h S7b(2) 10.P2e(6) B3c 11.P3f G4a-5b(4) +12.S3g(68) S4c(13) 13.P3e(2) Px3e(31) 14.S2f S3d(6) 15.R3h P4e(27) +16.Bx3c+(5) Nx3c 17.Sx3e(1) Sx3e(1) 18.Rx3e B'4d(36) 19.R3f(128) P'3e(92) +20.R2f(2) Bx9i+(29) 21.S'8h +B9h 22.P'3d(2) R4d 23.Px3c+(1) R8d +24.S6h-7g(21) P9e(38) 25.Px9e(30) S'9f 26.N'8f(2) R8e 27.G7i(56) Rx9e(4) +28.P'9i(46) Sx8g=(2) 29.Sx8g +Bx8g 30.Kx8g P'9h 31.K7h(1) Px9i+ 32.K6i(10) +L'8g(10) 33.K5i(5) +Px8i(1) 34.G7i-6h +P7i(11) 35.B'3d(1) R9i+(2) 36.K4h ++P6i(10) 37.+P4c(4) G5b-6b(15) 38.B'4d(3) +Px6h(29) 39.Sx6h S'3i 40.K5g(4) +N'6e 41.K6f +R9e 42.+Px5c(15) +R8d 43.B4c+(17) +Rx4d(28) 44.+Bx4d B'9i +45.P'8h(14) Bx8h+(2) 46.S'7g Gx5c 47.+Bx5c Nx7g+ 48.Sx7g(7) G'6e 49.Kx6e(2) ++Bx7g 50.N'7d(4) Px7d(1) 51.Nx7d K7c 52.G'7e N'5b(6) 53.R'4c Resigns +# +# 33-rd Oi Title Match, 3-rd game, 4-th and 5-th August 1992. +# Black: Tanigawa Koji, Oi; White: Gouda Masataka, challenger. +1.P7f P8d 2.P2f P8e(1) 3.B7g P3d 4.S8h G3b(2) 5.G7h Bx7g+(1) 6.Sx7g S4b +7.S3h(2) S7b(2) 8.P4f(2) S8c(3) 9.S4g(10) S8d(1) 10.P9f P9d(7) 11.P6f(9) +K4a 12.P6e(13) P9e(48) 13.Px9e(143) Sx9e 14.Lx9e Lx9e 15.P'9g P'9h(53) +16.S'8h K3a(11) 17.P3f(1) L'9a(155) 18.K4h(45) G5a(64) 19.G5h(24) P9i+(2) +20.Sx9i(12) Lx9g+ 21.Nx9g Lx9g+ 22.P'9h(6) +L9f(51) 23.L'8i(45) R9b(35) +24.P6d(1) Px6d 25.B'6c P'9g 26.Bx8a+(1) R9e 27.+B7b(2) Px9h+ 28.Sx9h P'9g +29.P'6c Px9h+(1) 30.P6b+(1) R9b 31.+Bx7c(20) Gx6b(5) 32.P'9c R7b(9) +33.+Bx7b(4) Gx7b 34.R'6a(1) K2b(1) 35.P2e B'1e(14) 36.K3h(1) +Px8i(1) +37.P1f(1) L'2f 38.Px1e S'4i(1) 39.Kx4i(3) Lx2h+ 40.K5i(1) R'3i(4) 41.N'4i +B'2g(6) 42.G4h(5) +L3h 43.Sx3h(3) Bx3h+ 44.B'4a(3) N'4g(1) 45.K5h(1) S'6i +46.Kx6i(7) +Bx4h 47.Bx3b+ Kx3b 48.S'4a K2b 49.Resigns +# +# 33-rd Oi Title Match, 4-th game, 17-th and 18-th August 1992. +# Black: Gouda Masataka, challenger; White: Tanigawa Koji, Oi. +1.P7f P8d(1) 2.S6h P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b 6.G7h(1) G3b 7.K6i(1) +K4a 8.G5h P7d(13) 9.P6f(14) S6b-5c(7) 10.P2f(53) P5e(21) 11.Px5e(41) Bx5e +12.P2e(3) S5d(5) 13.G5h-6g(14) R5b(24) 14.P2d(15) Px2d(1) 15.Rx2d P'2c(10) +16.R2h B8b(7) 17.S6h(14) S3c(99) 18.P'5f(72) P'5e(12) 19.Px5e(9) Sx5e +20.P6e K3a(20) 21.S4h-5g(53) G5a(21) 22.P'5f(7) S5e-4d 23.K7i G5a-4b +24.P4f(27) P8e(8) 25.P3f(30) P9d(9) 26.P9f(12) P6d(34) 27.Px6d Bx6d +28.P'6e(3) B7c(2) 29.N3g R6b(12) 30.B6f(16) Rx6e(8) 31.P7e(19) Px7e(7) +32.N7g(4) R6a 33.Nx8e(8) B8d 34.P4e(5) P'6e(2) 35.B8h S5c 36.P3e N7c(18) +37.Px3d(17) S2b(1) 38.P3c+ Sx3c(4) 39.N2e(15) Nx8e(3) 40.Nx3c+ Nx3c +41.P'3d N'6f(2) 42.Sx6f Px6f(8) 43.Bx6f S'7g 44.Px3c+(5) Sx6f+(5) +45.S'2b(8) Gx2b(3) 46.+Px2b Kx2b 47.N'3d(9) K3b 48.N'3e(4) +Sx6g(25) +49.Gx6g P7f(1) 50.Rx2c+ K4a 51.Nx4b+ Sx4b 52.G'3b K5a 53.Gx4b K6b 54.G'7d +S'8h(5) 55.Kx8h B'6f 56.P'7g Px7g+ 57.Sx7g Nx7g+ 58.Gx7g N'7f 59.Resigns +# +# 33-rd Oi Title Match, 5-th game, 25-th and 26-th August 1992. +# Black: Tanigawa Koji, Oi; White: Gouda Masataka, challenger. +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b(1) 6.G4i-5h(2) +G3b(2) 7.P6f(1) K4a 8.G6g S6b-5c(36) 9.G7h(9) P5e(28) 10.Px5e(7) Bx5e +11.P2f S5d(67) 12.P2e(6) R5b(26) 13.K6i(14) K3a(23) 14.P'5f(27) B3c(15) +15.S5g(18) P7d(22) 16.S7g-6h(9) S5c(28) 17.K7i(9) S4d 18.P4f(11) N7c(3) +19.P3f(8) B4b(3) 20.P1f(9) P8e(5) 21.B7g(11) P9d(23) 22.P9f(19) R8b(25) +23.P1e(35) G5b 24.L1h(16) S3c(17) 25.R3h(6) B6d(32) 26.P3e(1) Px3e 27.Rx3e +P'3d 28.R3h P4d 29.R4h(49) K2b(8) 30.P5e(8) Bx5e 31.S5f(5) B6d 32.P'5e +Sx5e(28) 33.Sx5e Bx5e 34.S'4a G3b-4b 35.Sx5b+ Rx5b 36.G'5f(6) S'3f(23) +37.P2d(20) Px2d(2) 38.Gx5e Rx5e(1) 39.P4e G'5h(6) 40.R2h(3) S4g+(33) +41.Px4d(3) R3e(1) 42.P'3g(11) P7e(2) 43.P6e(7) S'3b 44.B'5d(8) P8f(4) +45.Px8f(7) P'8g 46.Gx8g P'5c(7) 47.Bx6c+(13) Gx6h(4) 48.Gx6h(2) P'6g(1) +49.P'2c(6) Sx2c 50.G7h(3) S'6h 51.K8h Sx7g+ 52.Nx7g Px7f 53.P4c+(8) Gx4c +54.+B4a S3b(2) 55.S'3a(17) K2c 56.P'4d Gx4d 57.+B5a Px7g+ 58.G8gx7g P'4b +59.P'2b(23) Nx6e 60.Px2a+ Sx2a 61.Sx4b=(2) Sx4b 62.+Bx4b S'3c 63.+B3a Nx7g+ +64.Gx7g P'8g 65.Gx8g G'2b 66.P'2e(11) Px2e 67.N'1f N'7e 68.P'2d(1) Sx2d +69.Nx2d Nx8g+ 70.Kx8g G4c 71.N'3f(2) Rx3f 72.Px3f B'5d 73.P'6e(1) Bx6e +74.S'7f B5d 75.Rx2e Resigns +# +# 33-rd Oi Title Match, 6-th game, 8-th and 9-th September 1992. +# Black: Gouda Masataka, challenger; White: Tanigawa Koji, Oi. +1.P7f P8d(1) 2.S6h P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b 6.G4i-5h G3b 7.P6f K4a +8.G6g P7d(3) 9.G7h(8) G5b(3) 10.K6i S3c(1) 11.P3f B3a(1) 12.B7i P4d +13.S3g(51) B6d(12) 14.B6h G5b-4c(3) 15.K7i K3a 16.K8h P8e(13) 17.P1f(3) +K2b(1) 18.P2f P7e(43) 19.P6e(84) B4b(4) 20.Px7e(44) Bx7e 21.S4h S7c(21) +22.B4f(7) P4e(15) 23.B3g R9b 24.S5g(2) B5c(15) 25.S5g-6f(4) P3e(38) +26.Px3e(1) P'3f(1) 27.B5i(52) P6d(13) 28.Px6d(33) Sx6d(6) 29.S7f(11) +P'7e(35) 30.Sx8e(1) Bx3e 31.P'6e(14) Sx6e(10) 32.Sx6e P'6f 33.Gx6f(2) +B5g+(9) 34.G7h-6g(38) +B3i(44) 35.R7h N7c 36.Rx7e(44) Nx8e(1) 37.B8f(1) ++Bx2i(36) 38.R7a+(29) +Bx1i(1) 39.P5e(18) +B3g(5) 40.S'4a(4) +Bx2f(27) +41.P'6b(5) G4c-4b(6) 42.Sx3b+(4) Gx3b 43.G'3a(1) P2d(2) 44.P'3d(1) P'7h(27) +45.Px3c+(6) Gx3c 46.P'3d K2c(8) 47.Px3c+ Nx3c 48.+R4a(1) +B3e(1) 49.+R4c(4) ++B7i(2) 50.K9h Resigns +# +# 40-th Osho Title Match, 1-st game, 17-th and 18-th January 1991. +# Black: Yonenaga; White: Minami. +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S2b 7.S3h S7b 8.P4f +S3c 9.S4g K4b 10.G5h G5b 11.P3f S8c 12.N3g S8d 13.P9f P7d 14.P6f P7e 15.R2i P4d +16.K4h K3a 17.P6e Px7f 18.Sx7f R7b 19.S6g B'9b 20.P5f Bx6e 21.P2e S7e 22.P2d +Sx2d 23.P4e S6d 24.Px4d P3e 25.N7g B5d 26.B'6a R6b 27.B8c+ Px3f 28.N2e G5b-4b +29.P'6e P'7f 30.Px6d Px7g+ 31.Gx7g Px6d 32.P'7d N'6e 33.G6f N3c 34.Nx3c+ G4bx3c +35.N'4f N'4e 36.P'3h N6e-5g+ 37.Gx5g Nx5g+ 38.Kx5g Bx8g+ 39.P7c+ R4b 40.N'4e +G'3e 41.Nx5c+ Rx4d 42.G5e P'4e 43.N5d P4f 44.K6f Px4g+ 45.Gx4d Gx4d 46.K7e +Resigns. +# +# 40-th Osho Title Match, 2-nd game, 28-th and 29-th January 1991. +# Black: Minami; White: Yonenaga. +1.P7f P8d 2.S6h P3d 3.P6f S6b 4.P5f P5d 5.S4h S4b 6.G4i-5h G3b 7.G6g P7d 8.P2f +P6d 9.P2e S6c 10.P2d Px2d 11.Rx2d N7c 12.R2h P'2c 13.G7h P8e 14.B7g P4d 15.P4f +G5b 16.S4g R8a 17.P3f K6b 18.K6i P1d 19.S7i S5c 20.S8h R4a 21.B6h P4e 22.Px4e +P6e 23.Px6e Rx4e 24.P'4f P'6f 25.G5g R4a 26.N7g P7e 27.Px7e P3e 28.Px3e P8f +29.P3d R4d 30.R3h G3b-4c 31.R2h Rx3d 32.P'3e R3a 33.Rx2c+ B4d 34.P5e P'7f +35.Gx6f Px7g+ 36.Sx7g Px8g+ 37.Gx8g P'2b 38.+R2h Px5e 39.N3g N'5f 40.B7i G5d +41.S7f P'6g 42.Gx6g Gx6e 43.P'6f G6d 44.N4e S4b 45.P'5d Sx5d 46.P'5g P'6h 47.K7h +N3c 48.Px5f Nx4e 49.Px4e Sx4e 50.P'4f P'8f 51.Gx8f N'9d 52.G9f Sx5f 53.Sx5f Px5f +54.P7d P'7g 55.Gx7g P'7e 56.Px7c+ Kx7c 57.S8e P5g+ 58.N'6e Gx6e 59.S'7d K6b +60.Sx6e N'7c 61.N'5d K5a 62.S6d Nx8e 63.Gx8e S'6e 64.P'5c P7f 65.Px5b+ Kx5b +66.G'6c K4c 67.Nx4b+ Kx4b 68.S5c+ K3b 69.G'4b K2a 70.G3a Kx3a 71.N'4c K2a +72.R'3a K1b 73.S'2c Resigns. +# +# 40-th Osho Title Match, 3-rd game, 7-th and 8-th February 1991. +# Black: Yonenaga; White: Minami. +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f P1d 8.S3h +P6d 9.P7f P8f 10.Px8f Rx8f 11.P'8g R8b 12.P4f S6c 13.S4g P3d 14.S5f S5d 15.P9f +G5b 16.G5h P4d 17.K6i S4b 18.P3f S4b-4c 19.B7g K4a 20.N3g K3a 21.S8h G5b-4b +22.K7i P9d 23.P8f P7d 24.S8g N7c 25.B8h R8a 26.G5h-6h B3c 27.P1e Px1e 28.P3e +Px3e 29.P'1c G2b 30.N2e B2d 31.S5e N6e 32.Sx5d Px5d 33.P6f Nx5g+ 34.Gx5g S'3g +35.R2i P3f 36.B7g S3h= 37.R2h P3g+ 38.R1h Nx1c 39.Nx1c+ Lx1c 40.S'2e B3e 41.N'3d +Sx3d 42.Sx3d P'3c 43.Sx3c+ G2bx3c 44.N'2e G3c-4c 45.P'3f B2d 46.Nx1c+ Bx1c +47.Rx1e S'2d 48.Rx1c+ Sx1c 49.Lx1c+ R'1i 50.K8h Rx1c+ 51.P4e P7e 52.Px4d Gx4d +53.P6e P5e 54.L'4f P'4e 55.Lx4e Gx4e 56.B'5d R8c 57.P'4c Gx4c 58.Bx4c+ Rx4c +59.S'3d R4d 60.S'3c P'3b 61.G'4b Rx4b 62.Sx4b+ Kx4b 63.R'4c K3a 64.Rx4e+ L'5a +65.P'5b Lx5b 66.G'4b K2b 67.Gx3b Kx3b 68.+R4c K2a 69.+Rx5b G'3a 70.P'2b K1b +71.L'3c +Rx2b 72.P'2d Px2d 73.Lx3a+ +Rx5b 74.G'2c K1a 75.Bx5e +Rx5e 76.P'2b +B'5d 77.P2a+ Bx2a 78.S3c+ Resigns. +# +# 40-th Osho Title Match, 4-th game, 20-th and 21-st February 1991. +# Black: Minami; White: Yonenaga. +1.P7f P8d 2.S6h P3d 3.P6f S6b 4.P5f S4b 5.S4h P5d 6.G4i-5h G3b 7.G6g P7d 8.P2f +P6d 9.P2e S6c 10.P2d Px2d 11.Rx2d N7c 12.R2h P'2c 13.G7h P8e 14.B7g P4d 15.K6i +S5c 16.P3f P4e 17.S4h-5g S4d 18.N3g R4b 19.K7i K6b 20.K8h P9d 21.P4f Px4f +22.Sx4f P'4e 23.S4f-5g G5b 24.L9h P1d 25.K9i P9e 26.S7i N3c 27.S8h B1c 28.B6h +R4a 29.P1f B3a 30.S4h P8f 31.Px8f B5c 32.S4g P3e 33.Px3e Sx3e 34.P'3d P'3f +35.Px3c+ Gx3c 36.P'4b Px3g+ 37.Px4a+ +Px2h 38.P5e Px5e 39.P'5d Sx5d 40.P7e R'3g +41.R'8b K6c 42.P'3f S4d 43.Px7d S4c 44.P'4h Kx7d 45.N'3e G6b 46.+P4b P'8a +47.Rx8a+ Bx4b 48.Nx4c+ Gx4c 49.S'5a Bx5a 50.+Rx5a S5c 51.B3e N'4d 52.+Rx6b Sx6b +53.B'5b S'6c 54.P'7e Kx7e 55.Bx4c+ R3i+ 56.G'8c R'5i 57.G7f Resigns. +# +# 40-th Osho Title Match, 5-th game, 28-th February and 1-st March 1991. +# Black: Yonenaga; White: Minami. +1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S2b 7.S3h S3c 8.P4f +S7b 9.S4g K4b 10.G5h G5b 11.P6f S8c 12.P3f S8d 13.P9f P7d 14.N3g P4d 15.R2i S7c +16.P1f P1d 17.P9e G3b-4c 18.P2e K3b 19.K6h S6d 20.K7i P7e 21.P4e Px4e 22.Nx4e +S2b 23.S5f P8f 24.Px8f P'4d 25.P6e Px7f 26.Sx7f S7c 27.S8e Px4e 28.G5h-6g B'3g +29.P'7d S6b 30.Sx4e P'4d 31.S5f P5d 32.G6g-7g B4f+ 33.K8h +Bx5g 34.S6g +B4g +35.R5i +B3g 36.R4i G5b-4b 37.B'4f +Bx4f 38.Rx4f B'2h 39.R4i S3c 40.S6f P6d +41.Px6d Bx6d+ 42.P'6e +B3g 43.B'6d +Bx6d 44.Px6d B'3h 45.R5i B4g+ 46.S7f P'6h +47.Gx6h P'6c 48.P7c+ Nx7c 49.P'7d +Bx7d 50.S7f-7e +B4g 51.P'7d N6e 52.G7g-6g +P'8e 53.P6c+ Sx6c 54.K9g N'8c 55.S8d Nx9e 56.S7c+ +B3g 57.R5h Px8f 58.P'8c +B6d +59.B'7e P8g+ 60.K9f R8a 61.Bx6d Sx6d 62.Kx9e B'4i 63.K8d Bx5h+ 64.P8b+ +Bx6h +65.Gx6h G'9b 66.+Px8a +P8f 67.P'8e R'8h 68.R'9e P'8c 69.+Sx8c +Px8e 70.Rx8e Gx8c +71.Kx8c Rx8e+ 72.P'8d S'9b 73.Resigns +# +# 40-th Osho Title Match, 6-th game, 11-th and 12-th March 1991. +# Black: Minami; White: Yonenaga. +1.P7f P3d 2.P6f P3e 3.P5f R3b 4.S4h S4b 5.K6h K6b 6.K7h K7b 7.P9f P4d 8.G4i-5h +S4c 9.G6g P1d 10.B7g K8b 11.K8h L9b 12.S7h K9a 13.P8f S8b 14.S8g R3d 15.G7h B1c +16.P2f N3c 17.P2e G4a-5b 18.R2f S5d 19.P8e P6d 20.B8f S6c 21.S5g G7b 22.P9e +G5b-6b 23.P1f P4e 24.P5e P5d 25.P1e Px1e 26.Px5d Rx5d 27.P6e P3f 28.P'5e Rx5e +29.S5f R5d 30.B7g Px3g+ 31.Nx3g R3d 32.P'3f Px6e 33.Sx6e B3a 34.P2d Px2d 35.P3e +Rx3e 36.Rx2d P'6d 37.R2a+ B4b 38.+R2f R3d 39.P'3e R1d 40.S5f P'2e 41.+R3f P7d +42.P'2d P6e 43.P3d P'3e 44.+Rx3e B5c 45.+R3f P'3e 46.+R2g P2f 47.+Rx2f P3f +48.+Rx3f Rx2d 49.Px3c+ R2h+ 50.+P4c B2f 51.Nx4e B3g+ 52.+Rx3g +Rx3g 53.+P5c +Resigns. +# +# 41-st Osho Title Match, 1-st game, 16-th and 17-th January 1992. +# Black: Minami Yoshikazu; White: Tanigawa Koji. +1.P7f P3d(4) 2.P2f P4d 3.P2e B3c 4.S4h S3b(3) 5.P5f R4b(2) 6.K6h K6b 7.K7h +K7b 8.G4i-5h(6) K8b(11) 9.P9f(2) S4c(20) 10.S5g(14) G4a-5b(16) 11.P8f(4) +P6d(4) 12.K8g(9) L9b(51) 13.S7h K9a 14.P3f(69) S8b(1) 15.S4f G7a(42) +16.P3e(4) R3b 17.Px3d(125) Sx3d(1) 18.S5e S4c(46) 19.P'3d(9) B5a(107) +20.R3h(2) P7d 21.Sx4d(65) Sx4d 22.Bx4d S'4i(3) 23.R3i(19) Sx5h+(1) 24.Gx5h +B8d 25.R3e(7) G'5g(42) 26.P8e(49) Gx5h 27.Px8d R4b 28.Bx1a+ Rx4g+ 29.S'7g(8) +G'7i(28) 30.Px8c+(7) Sx8c 31.P'8d S7b(3) 32.L'8f(9) P'8b 33.+Bx2a Gx7h(12) +34.Kx7h G5g 35.G'7i(10) Gx6g 36.K8h +R4f(14) 37.R3g(6) +Rx3g 38.Nx3g R'3i +39.P'6i(2) Rx3g+ 40.R'4a N'6a(2) 41.B'5e(5) +R3h(5) 42.S'6h G5b-6b(3) +43.+B4c(17) S'5d(7) 44.Bx6d Gx7g 45.Nx7g S'7c 46.N'8c(1) Px8c 47.Px8c+ Sx8c +48.Lx8c+ Sx4c(1) 49.Rx6a+ G6bx6a 50.Bx7c+ Resigns +# +# 41-st Osho Title Match, 2-nd game, 27-th and 28-th January 1992. +# Black: Tanigawa Koji; White: Minami Yoshikazu. +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f P5d 5.S4h S4b 6.G4i-5h G3b 7.P6f K4a +8.G6g P7d 9.G7h(4) G5b(2) 10.K6i S3c 11.B7i B3a 12.P3f(1) P4d 13.B6h(23) +G5b-4c(22) 14.K7i B6d 15.N3g(2) K3a 16.K8h(1) K2b(17) 17.P2f(8) P8e(29) +18.R3h(4) S5c(12) 19.P4f(24) P5e(9) 20.Px5e(91) Bx5e 21.G5f B7c(33) 22.G6e +R8d(10) 23.S4g S6d(34) 24.Gx6d Bx6d 25.R5h P'5d(4) 26.S5f(4) N7c(15) +27.P9f(9) P9d(4) 28.P1f(8) P9e(54) 29.Px9e P7e(9) 30.Px7e Bx7e 31.S'7f(39) +B4b(20) 32.P'7e(7) P8f(12) 33.Sx8f(12) P5e(4) 34.S4g(2) P6d(39) 35.Rx5e(42) +P'5d 36.R5i P6e(3) 37.B5g(3) B6d(37) 38.P'5f(22) Px6f(2) 39.P'6e(12) B5c(7) +40.Bx6f(13) P'6d 41.Px6d(20) Rx6d 42.B4h P4e(11) 43.Nx4e(3) B4d 44.P5e +Bx5e(33) 45.P'6f(1) Rx6f(2) 46.Bx6f(32) Bx6f 47.S7g B4h+ 48.Nx3c+ Nx3c(4) +49.R6i P'6e 50.S5f(1) +B5h 51.R6h(3) +Bx6h 52.Gx6h R'5i(10) 53.P'6i(1) Rx5f+ +54.R'6a(2) P'4a(1) 55.S'5b(10) G4c-4b(1) 56.Sx4a+ Gx4a 57.Rx4a+ G'3a 58.+Rx9a +B'5e(14) 59.L'5g(16) N'8d 60.Lx5f(19) Nx7f 61.K7h Nx6h+ 62.Px6h Bx7g+ 63.Nx7g +P'7f 64.B'4d G'4c(12) 65.R'8b(1) S'4b(1) 66.N'2e S'4a(4) 67.B6b+(8) S'6f +68.K8h(1) Px7g+ 69.K9g Sx7e 70.+Bx7c N'8d 71.+Bx8d Sx8d 72.Rx8d+ Nx2e +73.K8f(1) P'8c(1) 74.+R7d(2) B'5g(1) 75.K8e N'6b 76.+Rx8c S'7d 77.K9d Sx8c +78.Kx8c N3g+(1) 79.P9d(1) R'8i(1) 80.P9c+ Rx9i+ 81.B'7c L'8a(1) 82.K7b Bx9c+ +83.Kx8a Resigns +# +# 41-st Osho Title Match, 3-rd game, 5-th and 6-th February 1992. +# Black: Minami Yoshikazu; White: Tanigawa Koji. +1.P7f P3d(1) 2.P2f P8d(1) 3.P2e P8e 4.G7h G3b 5.P2d Px2d 6.Rx2d P8f(4) 7.Px8f +Rx8f 8.Rx3d(3) Bx8h+(34) 9.Sx8h Rx7f 10.N7g(24) G3c(47) 11.R8d(11) P'8b(5) +12.K5h(33) R2f(9) 13.P'2h K5b 14.G3h(3) G7b(2) 15.P2g R2b 16.R8f(1) P8c(5) +17.P9f(17) P1d(9) 18.P9e(55) S8b(8) 19.R5f(39) S4b(21) 20.P3f(1) P7d(11) +21.N3g(58) P4d(24) 22.P3e(15) P1e(148) 23.R2f(67) P'2d(2) 24.R5f(16) P2e(25) +25.S8g(14) P6d(14) 26.P1f(25) P'3f 27.Rx3f B'6c 28.R6f(6) Px1f 29.Rx6d(14) +P1g+(36) 30.N6e(12) N7c(10) 31.B'8a(12) P'6b(8) 32.P3d(10) G4c 33.Nx7c+(3) +Gx7c 34.Bx6c+ Px6c 35.R6f B'5e(2) 36.R9f(3) +Px2g(4) 37.Lx1a+(5) +Px3h(4) +38.Sx3h N'2f 39.L'5f(1) B6d 40.N'7f(5) B7e(3) 41.S2g P9d(2) 42.Px9d G'8e(2) +43.R9h P'9f 44.R8h(3) Lx9d(5) 45.P'9h P9g+(3) 46.Px9g Lx9g+ 47.Lx9g Bx9g+ +48.R8i P'3f 49.+Lx2a(3) Rx2a(1) 50.N'5e Gx3d(3) 51.L'6f(5) Px3g+(8) +52.P'9h(1) +B7e(2) 53.Sx2f(3) Px2f 54.Lx6c+(8) Gx6c 55.Nx6c+ Kx6c 56.N'5e +K6b(1) 57.G'6c(1) K7a(2) 58.P'7c K8a 59.P7b+ K9b 60.+Px8b Kx8b 61.P'8d(2) +N'6e(2) 62.P6f +Bx6f(1) 63.B'6d K9c 64.Px8c+ K9d(1) 65.S'9e Kx8c 66.P'8d K9b +67.G6g +Bx6g 68.Kx6g P'6f 69.Kx6f G'7e 70.Resigns +# +# 41-st Osho Title Match, 4-th game, 17-th and 18-th February 1992. +# Black: Tanigawa Koji; White: Minami Yoshikazu. +1.P2f P8d(2) 2.P2e P8e 3.G7h(2) G3b 4.P2d Px2d 5.Rx2d P'2c(8) 6.R2f S7b +7.P1f(6) P1d(1) 8.P9f(7) P6d(9) 9.S3h(39) S6c(6) 10.P7f(2) P8f(3) 11.Px8f +Rx8f 12.N7g P9d(28) 13.K4h(5) S4b(21) 14.B9g(55) R8b(112) 15.P7e(1) P3d(1) +16.R8f(40) P'8d 17.P6f(16) K4a 18.S6h P4d(14) 19.S6g(6) G4c 20.S5f(40) K3b(6) +21.R7f(4) P5d(16) 22.P6e(38) S5c 23.Px6d(1) S5cx6d 24.S6e Sx6e(7) 25.Nx6e(8) +S'6d 26.P'6f P4e(2) 27.L9h(7) Sx6e(61) 28.Px6e(1) B9i+ 29.P'8c(21) R5b(66) +30.S'8g(23) +B3c(6) 31.K3i P5e(1) 32.G6h(5) R6b(22) 33.G6h-5h(12) G5b(14) +34.S'7a(16) R6a 35.P8b+ P5f(13) 36.Rx5f(16) S5d 37.S7f(1) S5e(6) 38.R3f(3) ++B4d(2) 39.+P7b(2) R6c(1) 40.P7d(2) Px7d(3) 41.P5f(11) S6f(1) 42.P6d(14) R9c +43.+P6b Gx6b 44.Sx6b= +Bx6b 45.P6c+ +Bx6c(5) 46.G'3a(8) K2b 47.G6g Sx6g+(5) +48.Sx6g G'4a(2) 49.P'2d(5) Px2d(1) 50.Gx2a(1) Kx2a 51.N'5e +B5b(7) 52.Nx4c+ +Rx4c 53.Rx3d(3) G'3b 54.G'4d(5) S'2c(2) 55.Rx3b+(4) Gx3b(1) 56.Gx4c +Bx4c +57.R'4a P'3a 58.G'4b(6) +Bx4b(2) 59.Bx4b+(2) Gx4b(1) 60.Rx4b+ R'3b(2) +61.P'2b(4) Rx2b 62.+Rx2b Kx2b 63.R'8b G'3b(1) 64.B'6f P'5e 65.Bx5e N'3c +66.G'4c P'6b(3) 67.Gx3b(1) Px3b 68.Rx8a+ G'2a(3) 69.B6d(4) R'6h(10) +70.N'4c(1) Resigns(2) +# +# 41-st Osho Title Match, 5-th game, 27-th and 28-th February 1992. +# Black: Minami Yoshikazu; White: Tanigawa Koji. +1.P7f G3b(6) 2.P5f(8) P5d(9) 3.R5h(2) S6b(7) 4.P5e(1) Px5e(1) 5.Bx5e K4a +6.B7g P3d(2) 7.P6f P'5e(20) 8.S6h S5c 9.S6g S5d 10.K4h S4b(3) 11.K3h R5b(13) +12.R8h(16) P4d(22) 13.P8f P4e 14.P8e R8b 15.K2h(21) K3a 16.P7e(22) B4d(6) +17.G3h(14) K2b(1) 18.P6e(31) S4b-4c(24) 19.S6f(1) B3c 20.R8f(13) G5b(13) +21.G5h(18) G5c(38) 22.R7f(37) P6d(50) 23.P7d Px7d(1) 24.Rx7d P'7c 25.R7f +Px6e(34) 26.S7e R7b(36) 27.P'5i(18) P7d(28) 28.Sx7d P'7e(4) 29.Rx7e G6d +30.P'7c Gx7e(1) 31.Px7b+ Gx7d 32.+Px8a(9) R'6i(4) 33.R'7b(3) Gx8e(1) +34.+Px9a(5) Rx8i+ 35.P4f(3) Px4f(59) 36.P'4b(2) N'3e(1) 37.L'4i(4) P4g+(7) +38.Lx4g(3) Nx4g+(1) 39.G5hx4g L'4d(1) 40.N'2e B2d(5) 41.N'3f(4) Lx4g+(2) +42.Gx4g +R7h(9) 43.L'4h(4) B7i+(6) 44.P4a+(10) P'4f(14) 45.Gx4f(7) +Bx4f(12) +46.P'6h(16) P'4g(7) 47.P'4d(1) +Rx7g(3) 48.Rx7g+ G'3h 49.Kx3h Px4h+ 50.Sx4h +B'5f 51.G'4g L'4e(2) 52.R'5g(2) +Bx4g(5) 53.Sx4g Lx4g+ 54.Rx4g S'4f 55.L'4i +S'5g(4) 56.Resigns +# +# 42-nd Osho Title Match, 1-st game, 13-th and 14-th January 1993. +# Black: Tanigawa Koji; White: Murayama Satoshi. +1.P7f P8d(1) 2.S6h P3d(1) 3.P6f S6b(2) 4.P5f P5d 5.S4h(2) S4b(2) +6.G4i-5h G3b(2) 7.G6g(1) K4a(8) 8.G7h(3) G5b(5) 9.K6i(1) S3c(1) +10.S7g(1) B3a(1) 11.B7i(2) P4d(2) 12.P3f(5) P7d(15) 13.B6h(14) P9d(32) +14.K7i(34) P9e(7) 15.K8h N7c(9)16.P3e(26) L9c(17) 17.Px3d(23) Sx3d(1) +18.R3h S4c(19) 19.B4f(2) R9b(4) 20.S8f(5) P6d(4) 21.S5g(10) S6c(15) +22.P'3d(27) B5c(13) 23.P5e(9) Px5e(32) 24.Bx5e G5b-4b 25.S5f(9) K3a(6) +26.P1f(12) K2b(12) 27.B4f(42) S6c-5d(14) 28.P'5e(14) S4e(10) 29.Sx4e(4) +Px4e 30.B2h P'3e(16) 31.S'8c(28) R5b(36) 32.Sx7d=(19) B4d(10) +33.Sx7c=(4) Bx5e(13) 34.Bx5e(2) Rx5e 35.P'5f(10) R5d(1) 36.S7g Rx3d(38) +37.Sx6d=(35) B'4i(15) 38.R2h P3f(1) 39.N'2f(11) R3e(8) 40.S6h(1) +P3g+(17) 41.Nx3g S'4d(4) 42.P'3f(16) Rx3f 43.P'3h B5h+(6) 44.G5g(14) ++Bx7f(10) 45.S6g +B8e 46.P4f(1) Px4f(4) 47.B'8b +Bx6g(26) 48.G7hx6g S'4h +49.S5e(39) Sx3g+(9) 50.Px3g(1) Rx3g+ 51.R7h(6) P4g+(2) 52.Sx4d +Px5g +53.Bx3g+ +Px6g 54.R7a+ G'7h(8) 55.+Rx7h +Px7h 56.Kx7h R'5g(3) 57.R'6g(4) +P'7g(1) 58.Rx7g(2) Rx7g+(2) 59.Nx7g N'7e(5) 60.B'7f(1) G'6g(6) +61.Bx6g(12) R'5g 62.S'7f Nx6g+ 63.Sx6g Rx3g+ 64.N'3d Sx3d 65.Nx3d +Rx3d +66.S'3e +R4e 67.G'4f +Rx4d(3) 68.Sx4d P'7f 69.P'3c(1) Px7g+ 70.Kx7g B'5i +71.K7f G4bx3c 72.Sx3c+ Nx3c 73.P'3d S'8e 74.K7e Resigns (1) +# +# 42-nd Osho Title Match, 2-nd game, 27-th and 28-th January 1993. +# Black: Murayama Satoshi; White: Tanigawa Koji. +1.P7f P8d 2.P2f(3) P8e(2) 3.B7g P3d 4.S8h G3b(1) 5.G7h(1) Bx7g+(8) +6.Sx7g S4b 7.S3h S7b(1) 8.P4f(2) K4a(17) 9.S4g(1) S8c(3) 10.P3f(2) +S8d(1) 11.P9f(6) P9d(5) 12.G5h(2) K3a(9) 13.N3g(2) G5b(8) 14.P4e(20) +S3c(57) 15.S6f(50) P7d(6) 16.K4h(20) S7c(3) 17.S5e(7) P8f(24) 18.Px8f(1) +Rx8f 19.R2i(5) R8b(29) 20.N7g(31) P6d(26) 21.P4d(63) Px4d(6) 22.P'4e(1) +P5d(36) 23.S5e-4f P'8g(20) 24.Px4d(15) P8h+(4) 25.P'8c(13) Rx8c 26.B'6a +R8b 27.Gx8h Sx4d(9) 28.G7h(3) P'4c(17) 29.Bx5b+(17) Rx5b 30.R8i P'8d +31.G'8c(1) S5e(45) 32.Gx7c(55) Nx7c(2) 33.Rx8d Sx4f(2) 34.R8a+ K2b +35.Sx4f S'6i(18) 36.G7h-6h(15) B'2g(2) 37.S'4i(6) Sx5h+(19) 38.Gx5h(2) +G'2h(1) 39.G5i(24) G'3i(19) 40.N2e(21) B'6i(39) 41.Gx6i(30) Bx4i+ 42.K4g +S'5h(6) 43.K5f +B3h 44.K6f(2) P6e 45.Nx6e(1) +Bx6e 46.K7g N'8e(2) +47.K8g(3) Sx6i= 48.Resigns (2) +# Time black: 7.07; time white: 7.27. +# +# --------------------------------------------------------------------------- +# +# 42-nd Osho Title Match, 3-rd game, 9-th and 10-th February 1993. +# +# Black: Tanigawa Koji; White: Murayama Satoshi. +# +1.P7f P8d(2) 2.S6h P3d(1) 3.P6f S6b(2) 4.P5f P5d(1) 5.S4h S4b 6.G4i-5h +G3b(1) 7.G6g(1) K4a(1) 8.G7h(3) G5b(1) 9.K6i S3c 10.S7g(1) B3a(1) 11.B7i +P4d(5) 12.P3f(2) P7d(3) 13.B6h(26) G5b-4c(18) 14.K7i(4) P8e(3) +15.K8h(19) B6d(6) 16.S3g(12) K3a(7) 17.P2f K2b(10) 18.P1f S7c(28) +19.S4f(5) P7e(53) 20.Px7e(5) P4e(53) 21.S3g(1) Bx7e 22.P'7f(16) B6d(14) +23.P2e(6) S6b(2) 24.P4f(37) Px4f(6) 25.Bx4f Bx4f(9) 26.Sx4f(2) P'4e +27.S3g S5c(1) 28.P7e(77) P5e(2) 29.Px5e(37) S5c-4d(16) 30.P5d(38) +Gx5d(2) 31.P7d G6d(7) 32.P2d(1) Px2d(1) 33.P'2e Px2e(4) 34.N1g(24) +P'7f(14) 35.Sx7f(1) P'7e 36.Nx2e(1) P'2c(6) 37.Nx3c+(15) Sx3c 38.P'4d(8) +Px7f(18) 39.S'4c P8f(1) 40.Sx3b+(23) Kx3b(1) 41.B'4c K2b(2) 42.Px8f +P'8g(13) 43.Gx8g(12) N'7e(20) 44.Bx7f+(3) B'6i 45.P4c+(9) Nx8g+(63) +46.+Bx8g Bx8g+ 47.Kx8g B'6i 48.K7g(5) S'3b 49.P'4d(5) Resigns (13) +# Time black: 6.39; time white: 6.59. +# +# --------------------------------------------------------------------------- +# +# 42-nd Osho Title Match, 4-th game, 17-th and 18-th February 1993. +# +# Black: Murayama Satoshi; White: Tanigawa Koji. +# +1.P7f P8d 2.S6h(6) P3d 3.P6f(1) S6b 4.P5f(2) P5d 5.G4i-5h(1) S4b(1) +6.S4h(2) G3b(2) 7.G6g(4) K4a 8.G7h(4) G5b(6) 9.K6i(3) S3c(4) 10.S7g(3) +B3a(2) 11.B7i(6) P4d 12.P3f(3) G5b-4c(3) 13.B6h(1) P7d(26) 14.K7i(2) +P8e(1) 15.K8h(5) B6d(23) 16.N3g(5) K3a 17.R3h(1) K2b(1) 18.P2f(3) S5c(6) +19.P1f(14) P5e(27) 20.P6e(27) B7c 21.Px5e(2) P6d(13) 22.N2e(5) S2d(10) +23.P3e(9) Sx3e(17) 24.P1e(4) Px6e(41) 25.Nx1c+(15) Lx1c(21) 26.P1d(15) +Lx1d(10) 27.Lx1d(3) P'1c 28.Lx1c+(9) Kx1c(1) 29.P'3f(20) L'6f(17) +30.Px3e(44) P8f(2) 31.Px3d(28) K2b(1) 32.Sx8f(2) Lx6g+(54) 33.Gx6g(2) +G'6f 34.G7g(16) N'5f(9) 35.B7i(14) P'8e(36) 36.Sx8e(1) Nx4h+(3) +37.Rx4h(8) Bx5e(3) 38.S'7h(3) P'5f(6) 39.L'5i(8) P7e(33) 40.R1h(73) +N7c(4) 41.Gx6f(2) Bx6f 42.G'7g(2) P'1g(2) 43.Rx1g(15) B3i+ 44.N'1d(28) +K3a(1) 45.S7d(1) N8e(6) 46.Sx8e(2) +Bx1g 47.Lx5f(14) R'5i(8) 48.Lx5c+(4) +Gx5c 49.L'5g(9) Px7f(3) 50.S'6h(10) Px7g+(6) 51.Nx7g R5h+ 52.P'5i +R3h +53.Lx5c+ +Rx3d 54.S6h-6g(5) P6f(4) 55.Sx6f(1) P'6h(3) 56.Bx6h(7) G'5f(1) +57.N'1c(4) P'6g(3) 58.Nx2a+ Kx2a 59.B1c+ L'1a 60.P'3c(1) Lx1c(2) +61.Px3b+ Rx3b 62.P'3c +Rx3c 63.N'2e S'7i(1) 64.Resigns +# Time black: 7.59; time white: 7.03. +# +# 38-th Oza Title Match 1990 (professional, no comment). +# +# +# 38-th Oza Title Match, 1-st game, September 9-th 1990. +# Black: Nakahara, Oza; White: Tanigawa, Oi +# +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f P1d 8.S3h +P3d 9.K5h P9d 10.P3f B4d 11.P3e Bx3e 12.R5f S4b 13.P7f B4d 14.Bx4d Px4d 15.N7g +P6d 16.P1e Px1e 17.P'1c Lx1c 18.R5e N3c 19.G3i S6c 20.Rx8e P'8d 21.R8f S5d +22.P7e S4b-4c 23.P7d G7b 24.P'1d Lx1d 25.B'3f Px7d 26.Bx1d P3e 27.R2f S3d 28.S6h +G6c 29.N3g P7e 30.P8f G2b 31.L'5f G1c 32.N2e Nx2e 33.Bx2e Sx2e 34.Rx2e N'4f +35.K6i B'5h 36.K7i Nx3h+ 37.Gx3h S'6i 38.G8h G2d 39.R2i P7f 40.Rx6i Px7g+ +41.Sx7g N'6e 42.R6h Nx5g+ 43.N'7e +Nx6h 44.Kx6h B4i+ 45.Nx6c= Sx6c 46.P'5i N'6e +47.S6f R7b 48.Lx5c= P'5b 49.P'7g P'7f 50.Px7f Rx7f 51.S'7g B'5g 0-1 +# +# --------------------------------------------------------------------------- +# +# 38-th Oza Title Match, 2-nd game, September 13-th 1990. +# Black: Tanigawa, Oi; White: Nakahara, Oza +# +1.P7f P8d 2.S6h P3d 3.P6f S6b 4.P5f P6d 5.G7h S6c 6.G5h P6e 7.S7g Px6f 8.Sx6f +P8e 9.G5h-6g P8f 10.Px8f Rx8f 11.S7e R8b 12.P'8d P'6d 13.Bx2b+ Sx2b 14.G7h-7g +P7d 15.S6f N7c 16.R8h P'8e 17.G7h K4b 18.N7g Rx8d 19.B'9e R8c 20.P'8d R8a +21.Nx8e Nx8e 22.Rx8e P9d 23.N'7c Px9e 24.Nx8a+ N'3e 25.S4h B'3h 26.+Nx9a Bx2i+ +27.R'9b S5b 28.P8c+ +B3h 29.G5g B'5d 30.G7h-6g N'4e 31.G5h Nx3g+ 32.Sx3g +Bx3g +33.K6h Nx4g+ 34.Gx4g +Bx4g 35.K7g +B5h 36.P'6h S'7e 37.Sx7e Px7e 38.N'4f B6c +39.Rx7e P'8e 40.L'8i G'6e 41.Rx8e Bx8e 42.Lx8e S'7e 43.Px7e R'7f 0-1 +# +# Time used = Black: 4.45, White:3.19 +# +# --------------------------------------------------------------------------- +# +# 38-th Oza Title Match, 3-rd game, September 25-th 1990. +# Black: Nakahara, Oza; White: Tanigawa, Oi +# +1.P2f P8d 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2h P8f 7.Px8f Rx8f +8.P'8g R8d 9.S3h S7b 10.P7f P9d 11.P9f P1d 12.P4f R7d 13.G7g R2d 14.P'2e R8d +15.S4g P3d 16.P2d Px2d 17.Rx2d P'2c 18.R2h P6d 19.S3f P6e 20.K6h S6c 21.G5h G5b +22.P1f B3c 23.S4e S2b 24.P6f Px6f 25.S7h P2d 26.K7i S2c 27.Gx6f R8b 28.G5h-6g +K4a 29.P3f P9e 30.Px9e P'9g 31.Lx9g S7d 32.N7g N9c 33.P3e P'6e 34.G6f-5f Px3e +35.P'3d B2b 36.P9d N8e 37.Nx8e B8h+ 38.Kx8h Rx8e 39.B'5e P'9f 40.Lx9f N'8d +41.N'3c Nx3c 42.Px3c+ Nx9f 43.K7i B'8h 44.K6h Bx5e+ 45.+Px3b Sx3b 46.Gx5e L'6f +47.P'3c Sx3c 48.B'2c K5a 49.S5f N'3f 50.R1h N8h+ 51.N'6d R9e 52.Nx5b+ Kx5b +53.G'8i +Nx8i 54.Sx8i R9i+ 55.N'6d K6b 56.B4e+ B'9e 57.K5h Lx6g+ 58.Sx6g B5i+ +59.K4g N'6c 60.G'7b K5a 61.+B2c S4d 62.+Bx2d K4a 63.Gx4d N4h+ 64.Rx4h G'3f + 0-1 +# +# --------------------------------------------------------------------------- +# +# 38-th Oza Title Match, 4-th game, October 2-nd 1990. +# Black: Tanigawa, Oi; White: Nakahara, Oza +# +1.P7f P8d 2.S6h P3d 3.S7g S6b 4.S4h S4b 5.P5f P5d 6.G4i-5h G3b 7.P6f P6d 8.G6g +S6c 9.P2f P5e 10.Px5e Bx5e 11.P2e B2b 12.G7h K4a 13.K6i P7d 14.S5g S5d 15.P2d +Px2d 16.Rx2d P'2c 17.R2h R5b 18.P'5f G6b 19.K7i G6c 20.S7g-6h N7c 21.S4f P4d +22.P5e Sx5e 23.P7e Sx4f 24.Px4f Px7e 25.P'7d N8e 26.P8f S'5h 27.Px8e Sx6g+ +28.Gx6g P'5a 29.S'7h Px8e 30.B7g P8f 31.Bx8f G'8e 32.B7g P7f 33.B8h P'8g 34.Sx8g +P'8f 35.S7h G7e 36.N'1e P2d 37.P'2e R8b 38.P'8e B3c 39.Px2d P'2b 40.P2c+ Px2c +41.Nx2c+ P'2b 42.+Nx3c Nx3c 43.P6e N'9e 44.Bx4d P8g+ 45.S'8d Gx8e 46.P'8c R5b +47.Sx9e P'8f 48.B7a+ Gx9e 49.P'5g S'8h 50.K6i +Px7h 51.Kx7h Sx8i= 52.K6i S'3i +53.R3h P8g+ 54.N'4d P7g+ 55.Sx7g N'5e 56.G6h N4g+ 57.Nx5b+ Px5b 58.R'6a N'5a +59.Rx3i +Px7g 60.Gx7g +Nx5g 61.R3h P'4h 62.S'6h S'4g 63.Sx5g Sx3h= 64.P7c+ G8f +65.+Px6c Gx7g 66.+Px5b K3a 67.+Px4b Gx4b 68.Rx5a+ G'4a 69.N'2c Px2c 70.N'4c K3b +71.G'2b 1-0 +# +# Time used = Black: 4.50, White:4.57 +# +# Black: Fukuzaki Bungo, challenger; White: Tanigawa Koji, Oza +# +1.P7f(1) P8d(1) 2.P5f(3) P8e(5) 3.B7g P5d 4.R8h(1) P3d(2) 5.S6h S6b 6.K4h +P7d(20) 7.P6f(9) K4b(2) 8.K3h K3b 9.K2h G6a-5b 10.G6i-5h(6) S5c 11.S5g(13) +B3c(5) 12.L1h(3) K2b 13.K1i S3b 14.S2h P1d(3) 15.G3i(1) P2d 16.G6g(24) +S2c(5) 17.S4f(1) P4d(3) 18.P5e(8) Px5e(6) 19.Sx5e(3) P'5d 20.S4f G3b +21.B6h(7) G5b-4c(4) 22.P3f(4) P6d(15) 23.N7g(3) P2e(1) 24.S4f-3g(10) P5e(26) +25.P8f Px8f 26.P'8e P4e(1) 27.Rx8f P'8c 28.P9f(18) S4d(18) 29.R8i(1) B1e(9) +30.R5i(1) P8d(2) 31.P1f Bx3g+(6) 32.Nx3g Px8e 33.P4f P8f(44) 34.Px4e S3c +35.B'7a(57) R5b(10) 36.Nx2e(4) P8g+ 37.N8e +P8f(16) 38.Nx3c+(14) G4cx3c +39.S'4a N'4g(7) 40.Sx5b=(4) Nx5i+ 41.Bx5i(1) R'6i 42.B7a-2f+(1) +Px8e(13) +43.N'2e(24) N'4g 44.Nx3c+(1) Nx3c(1) 45.S4a=(4) Nx3i+(3) 46.Sx3b+ Sx3b +47.Sx3i P'2e(4) 48.+B4h(7) Rx6g+(2) 49.G'2h(6) P2f(9) 50.P'5g(4) Px2g+(2) +51.Gx2g P'4g 52.+Bx4g(20) S'5h(4) 53.+B4f(1) +Rx6f 54.P'2c(15) Resigns(1) +# +# Time used black: 4.47; white: 4.10 +# +# --------------------------------------------------------------------------- +# +# 39-th Oza Title Match, 2-nd game, 17-th September 1991. +# +# Black: Tanigawa Koji, Oza; White: Fukuzaki Bungo, challenger +# +1.P7f P3d(1) 2.P2f P4d 3.P2e B3c 4.S4h S4b(5) 5.P5f(1) R5b(1) 6.K6h K6b +7.K7h K7b(1) 8.G4i-5h K8b(2) 9.P3f(10) S4c(5) 10.P4f(4) G3b(4) 11.S5g(2) +L9b(2) 12.N3g(44) R5a(12) 13.P9f(7) P5d(5) 14.P9e(12) K9a 15.B6f(3) S8b(1) +16.S8h(1) S5b(22) 17.R4h(36) G7a(5) 18.N7g S5c(7) 19.P4e (41) Px4e 20.Bx3c+ +Nx3c 21.Nx4e Nx4e 22.Rx4e B'2g(19) 23.B'4g(8) N'3e(1) 24.B2i(4) Bx3f+ 25.R8e +P'4f(21) 26.P'4h(2) R4a 27.N'7e(41) G7b(11) 28.P5e(1) P4g+ 29.Gx4g Nx4g+ +30.Bx4g +Bx4g(7) 31.Px4g B'7d 32.S6h(8) G'7a(12) 33.G7i(7) Rx4g+(4) 34.P9d +Px9d 35.N'8f Bx8e(6) 36.Nx8e +R5f 37.S8h-7g(4) S6d 38.Nx9d(14) P'9h(40) +39.Lx9h(8) P'9g 40.Nx8b+ G7ax8b 41.P'9c Nx9c(2) 42.Nx9c+ Lx9c(6) 43.P'9d(11) +Lx9d(6) 44.P'9b(5) Kx9b(11) 45.Nx6c+(1) N'8e(16) 46.+Nx7b Gx7b 47.S8f(5) +N'6f(12) 48.Px6f P'6g 49.Sx8e(3) Px6h+ 50.Gx6h S'8i(27) 51.K7g R'7h(6) +52.K8f(2) N'7d 53.Sx7d S7e 54.Kx7e Px7d 55.K6d +Rx5e 56.K5c S'6b 57.K5b(1) +Rx6h+ 58.Resigns +# +# Time used black: 4.45; white: 4.40 +# +# --------------------------------------------------------------------------- +# +# 39-th Oza Title Match, 3-rd game, 24-th September 1991. +# +# Black: Fukuzaki Bungo, challenger; White: Tanigawa Koji, Oza +# +1.P7f(1) P8d(1) 2.S6h(6) P3d(1) 3.P6f S6b 4.G4i-5h S4b(1) 5.S4h P5d 6.G6g(1) +G3b(1) 7.P5f(2) K4a 8.S7g P7d 9.G7h(2) G5b 10.B7i S3c 11.K6i(3) B3a +12.P3f(6) P4d(10) 13.B6h(12) G5b-4c(13) 14.K7i B6d 15.N3g(5) K3a(1) 16.K8h +K2b 17.P2f P8e(5) 18.R3h(2) S5c(4) 19.P1f(2) P1d(9) 20.P4f(15) P5e(16) +21.S4g(1) S5d(3) 22.L1g(2) Px5f(20) 23.Sx5f N7c 24.R1h(18) P'5e(12) 25.S4g +S2d 26.P2e(3) S3c(1) 27.P4e(20) Px4e(14) 28.P'4f P5f(83) 29.Gx5f(25) +Px4f(2) 30.Sx4f(3) P'5e 31.G5g(25) P8f 32.Sx8f(1) P'4e 33.Nx4e(2) S4d +34.R4h P7e 35.G5g-6g(19) Px7f(1) 36.P'7d(21) N8e 37.Gx7f(3) P'7g(23) +38.Nx7g(2) Nx7g+ 39.Bx7g N'8d 40.S8e(23) Nx7f(4) 41.Sx7f N3c 42.P6e(7) G'7e +43.P7c+ Gx7f(5) 44.+Px8b B7e 45.R2h(2) B3i+(1) 46.R2g +B4i(1) 47.R'7b +Nx4e(3) 48.P2d(7) +Bx2g(9) 49.Px2c+ Kx2c 50.P'2d Kx2d(7) 51.Rx3b+(1) Gx7g +52.Gx7g R'4h 53.Resigns +# +# Time used black: 4.02; white: 4.11 +# +# --------------------------------------------------------------------------- +# +# 39-th Oza Title Match, 4-th game, 1-st October 1991. +# +# Black: Tanigawa Koji, Oza; White: Fukuzaki Bungo, challenger +# +1.P7f P3d(1) 2.P2f P4d 3.S4h S4b(3) 4.P5f P5d 5.K6h(3) S6b(4) 6.K7h(2) +P7d(1) 7.S6h(2) R7b(7) 8.G4i-5h(6) P7e(6) 9.Px7e(2) Rx7e 10.S7g N7c(5) +11.P'7f(7) R7d 12.P6f N8e(4) 13.S8f(11) Rx7f(7) 14.K6g(8) R7b(1) 15.Sx8e +P8d(1) 16.S9f(11) P4e(6) 17.P2e(53) B3c(11) 18.P2d(32) Px2d 19.S5g P6d(10) +20.K6h S6c(2) 21.P3f(9) G3b(5) 22.N3g(6) S4c 23.G6g(3) S7d(1) 24.P8f(2) +S7e(19) 25.Nx4e(9) B4d 26.P'7f(19) Sx7f(2) 27.Gx7f Rx7f 28.S8g R7c(25) +29.S'5c(4) Bx5c(10) 30.Nx5c+ Rx5c 31.P6e P5e 32.Bx5e(2) Rx5e(22) 33.Px5e +P'5f(5) 34.Sx5f G'6f(4) 35.N'5c(46) G5b(16) P5d(4) G3a(53) 37.P'2b(2) K4b(9) +38.Px2a+(3) B'5g 39.K7h(1) Gx5f +Px3a(2) S'6g(3) 41.K8h N'7e 42.P'7g(13) +Nx8g+(4) 43.Kx8g B6f+ 44.N'7i(2) +Bx6e(3) 45.K8h +Bx5d 46.N4a+ K5c(1) +47.R'8c S'6c 48.N'7e P'7c(4) 49.Rx7c+(1) S'6b(4) 50.Nx6c+(1) +Bx6c +51.+Rx6c(1) Sx6c(1) 52.B'7a N'6b 53.S'4b(1) Gx4b(1) 54.+Nx4b P'7f(1) +55.+Nx4c(2) Kx4c 56.Bx6b+(1) Resigns +# +# Time used black: 4.31; white: 4.23 +# +# --------------------------------------------------------------------------- +# +# 39-th Oza Title Match, 5-th game, 14-th October 1991. +# +# Black: Fukuzaki Bungo, challenger; White: Tanigawa Koji, Oza +# +1.P7f P8d(1) 2.P5f(2) P3d(8) 3.P6f(2) S6b 4.S6h P5d 5.R5h(1) K4b(2) 6.K4h +K3b 7.K3h G6a-5b(6) 8.K2h(1) S5c(2) 9.L1h(2) B3c 10.K1i K2b 11.S5g P4d(1) +12.S4f(29) G4c(2) 13.P5e(1) P4e(14) 14.Sx4e(1) Px5e 15.S3f(6) S3b(6) +16.G7h(1) P8e(2) 17.B7g S5d 18.G6g(1) P2d(7) 19.P4f(4) S2c(4) 20.S2h(1) +G3b(2) 21.G3i P7d(10) 22.P9f(14) P1d(3) 23.P9e(4) P2e(7) 24.S4g(3) P3e(10) +25.P3f(6) Px3f(1) 26.R3h(3) B4b(19) 27.G5g(10) P8f(15) 28.Px8f Bx8f +29.R8h(1) P'8g(1) 30.Rx8g(12) P'8e 31.P'8h(11) B4b(18) 32.B5i(15) P8f(2) +33.R6g P8g+ 34.Px8g P'8h 35.Sx3f(1) Px8i+(1) 36.P4e +Px9i(5) 37.G4f(1) +B9g+(18) 38.B3g(9) R8e(2) 39.P'5f(1) +B7i(9) 40.Px5e(13) +Bx4f 41.Bx4f Sx5e +42.B6h(2) G'4f(6) 43.P8f(7) R8b(10) 44.Bx4f(15) Sx4f 45.G'5f B'7c(7) +46.P4d(7) G4c-3c(1) 47.Gx4f(43) Bx4f 48.P'3d Sx3d(2) 49.P'3e S2c 50.S'3d(5) +B7c(9) 51.P'5e(6) P'4b(25) 52.Sx2c+(5) G3cx2c 53.S'3d S'3c(3) 54.Sx3c+(1) +G2cx3c 55.S'3d(1) S'2c 56.Sx3c+ Gx3c 57.G'3d G'3b(2) 58.Gx3c Gx3c 59.G'3d +G'3b 60.Gx3c Gx3c 61.G'3d G'3b 62.Gx3c Gx3c Sennichite +# +# Time used black: 4.08; white: 4.03 +# +# --------------------------------------------------------------------------- +# +# 39-th Oza Title Match, Replay 5-th game, 14-th October 1991. +# +# Black: Tanigawa Koji, Oza; White: Fukuzaki Bungo, challenger +# +1.P7f P3d 2.P2f P4d 3.S4h S4b(5) 4.P5f P5d 5.G4i-5h G6a-5b(3) 6.S6h(2) S6b +7.S7g S3c 8.K6h K4b 9.K7h K3b 10.P6f B3a 11.G6g P7d 12.B7i S7c 13.S5g(1) G4c +14.P3f K2b 15.K8h G3b 16.G7h P8d(1) 17.N3g(1) P8e 18.S4f(2) S2d(1) 19.B6h(3) +S6d(2) 20.B5g(9) P9d(10) 21.P1f N7c 22.P1e(2) P7e 23.Px7e R8d 24.P3e(7) +P8f(6) 25.Sx8f Sx7e 26.Sx7e(5) Bx7e 27.P'7f B4b(1) 28.S'7e R8a(8) 29.Px3d(7) +P'3f(3) 30.N2e(2) K3a(2) 31.S7d(6) P4e(1) 32.Sx4e(3) P3g+ 33.R1h +Px4g(9) +34.B6h(1) P'4d 35.S3f +P3g(3) 36.S3e S'2g(1) 37.Sx7c=(2) Sx3e 38.Bx3e +Gx3d(2) 39.B6h(1) Sx1h= 40.P'4c Gx4c 41.S'8b(1) R4a(1) 42.Lx1h R'3h +43.P'3c(1) Nx3c 44.Nx1c+ K3b 45.N'3e(4) Lx1c 46.P1d(2) Gx3e 47.Px1c+ P'8f +48.Bx3e(1) N'9f 49.K7i B3a 50.S'2b(1) S'8h 51.K6i Bx2b 52.+Px2b Kx2b 53.L1c+ +K3b 54.Gx8h Nx8h+ 55.+Lx2c Kx2c 56.S'2d K3b 57.G'2c K4b 58.Sx3c+ Gx3c +59.Gx3c Kx3c 60.G'2d K2b 61.N'3d K3b 62.P'3c K4c 63.Resigns +# +# Time used black: 1.04; white: 0.59 +# +# 40-th Oza Title Match 1992 (professional, no comment). +# Black: Habu Yoshiharu, challenger; White: Fukuzaki Bungo, Oza +1.P2f P8d(1) 2.P2e P8e 3.G7h G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b 7.P1f(2) +P3d(3) 8.P1e(3) P6d(1) 9.R3f(22) G3c(3) 10.S3h(25) S6c(5) 11.P7f(1) P8f(2) +12.Px8f Rx8f 13.P'8g(2) R8b(10) 14.R2f S5d(3) 15.P3f G3b(1) 16.N3g B4d(3) +17.Bx4d(6) Px4d 18.S8h S6e(14) 19.P3e(31) Px3e(10) 20.B'5e(13) R4b(23) +21.P1d(3) Px1d 22.P'1c Lx1c(6) 23.N2e(27) S2b(4) 24.N7g(1) S7d(3) 25.Bx6d +K5b(7) 26.Nx1c+(14) Sx1c(2) 27.L'8b(2) S6c(11) 28.B2h(1) G7a(9) 29.Lx8a+ +Gx8a 30.Bx7c+ B'8b(13) 31.+Bx8b(2) Gx8b 32.P'2b(2) N3c(2) 33.P2a+(13) +N'3d(27) 34.R6f(40) P'6e(35) 35.Rx6e(22) P'6d(15) 36.R7e(1) P'7d(6) +37.R5e(1) P5d(4) 38.R5f(3) R4a(6) 39.P7e(7) Px7e(1) 40.P'7d(1) Sx7d(5) +41.Rx5d(5) L'5c(3) 42.B'5f(1) G7c(10) 43.Bx3d G4c 44.Rx4d(5) Gx3d 45.Rx4a+ +Kx4a 46.R'7a K3b(7) 47.Rx7c+ P'5b 48.N'5e(4) N4e(4) 49.G'4c(2) Kx2a 50.+R7a +K1b 51.G3b R'2b 52.Gx2b(1) Sx2b 53.N'2f(1) K1c(7) 54.Nx3d(2) B'2f +55.P'3g(1) Nx3g= 56.R'1b(1) Resigns +# Time used black: 4.28; white: 4.26 +# +# --------------------------------------------------------------------------- +# +# 40-th Oza Title Match, 2-nd game, 14-th September 1992. +# +# Black: Fukuzaki Bungo, Oza; White: Habu Yoshiharu, challenger +1.P7f(1) P8d 2.S6h P3d 3.P6f S6b 4.G4i-5h(1) S4b 5.S4h G3b 6.G6g K4a 7.G7h +P5d 8.K6i G5b 9.P5f(1) P4d(1) 10.S7g S3c 11.B7i B3a 12.P3f P7d(10) +13.S3g(9) B6d(1) 14.B6h(2) G5b-4c(1) 15.K7i(1) K3a 16.K8h P8e(1) 17.P1f(1) +K2b(1) 18.P2f(2) P9d(3) 19.P1e S7c(1) 20.S4f(1) P7e(1) 21.Px7e P4e +22.S3g(1) Bx7e 23.P'7f(1) B6d(3) 24.P2e(9) P9e(6) 25.P4f(6) Px4f(2) 26.Bx4f +P'4d(1) 27.R4h(4) S7d(12) 28.P3e(5) Px3e(1) 29.Bx6d(5) Px6d(10) 30.P'4e +Px4e(1) 31.B'7a R8c(1) 32.P2d(1) Px2d(18) 33.Bx3e+(3) P8f 34.Sx8f(1) P6e +35.P'2c(23) Gx2c(3) 36.+Bx4e Px6f(36) 37.Gx6f(48) B'5g(1) 38.G6f-6g +Bx4h+(1) 39.Sx4h P'6f(6) 40.G6g-6h S6e(13) 41.B'7b(22) R8b(6) 42.B6a+(1) +R4b(7) 43.+B5a(2) Sx7f(14) 44.P'4d(74) P6g+(1) 45.G6hx6g Sx6g+(8) 46.Gx6g +R'5h 47.P'6h(2) Rx4h+(1) 48.Px4c+(2) Rx4c 49.P'4d(14) R6c(15) 50.G'3b(16) +K1b 51.+Bx2c(1) Kx2c 52.Gx3c Nx3c(7) 53.+B4a(7) S'3b(19) 54.+Bx3b(10) +Kx3b(4) 55.S'4c Rx4c 56.Px4c+ Kx4c(2) 57.S'3e(8) B'6f(42) 58.S'7g(2) +S'7i(1) 59.Kx7i +R3i 60.G'6i(10) G'5h 61.S'7h(1) Gx6i(2) 62.Sx6i G'5h(2) +63.R'6c(1) K3b(1) 64.G'4c K2a 65.P'2b K1b 66.Resigns +# Time used black: 4.59; white: 4.27 +# +# --------------------------------------------------------------------------- +# +# 40-th Oza Title Match, 3-rd game, 22-nd September 1992. +# +# Black: Habu Yoshiharu, challenger; White: Fukuzaki Bungo, Oza +1.P2f P8d(1) 2.P2e(1) P8e 3.G7h(2) G3b 4.P2d Px2d 5.Rx2d P'2c 6.R2f S7b +7.P9f(1) P1d(1) 8.P7f P8f(5) 9.Px8f Rx8f 10.N7g S4b(1) 11.K4h(1) P9d(3) +12.S3h(1) K4a(2) 13.B9g(13) R8b(6) 14.P7e P3d(2) 15.R8f(5) P'8e(13) +16.R7f(6) G6b(2) 17.S6h(2) P6d 18.P6f(6) S6c(17) 19.S6g K3a(16) 20.S5f(1) +R8d 21.S4e(13) P3e(1) 22.K3i(1) P1e(10) 23.G6h(29) G7b(17) 24.G6h-5h(30) +P7d(9) 25.Px7d(41) Sx7d 26.P'8f(2) P'7e(25) 27.Px8e R8b 28.Bx7e(4) Sx7e +29.Rx7e Bx6f(3) 30.R7f B5e(2) 31.S'8c(4) Gx8c(7) 32.R7a+(3) K2b 33.P8d +B'6c(15) 34.S3d(5) S'3c(1) 35.Sx3c+(1) Sx3c 36.Px8c+(14) Rx8c 37.P'2d +S'3d(7) 38.P'8d(14) R7c 39.+Rx7c Nx7c 40.R'6b B5d(14) 41.S'4a(1) G4b(10) +42.G'3b(6) K1c 43.Gx4b(1) Bx7g+(3) 44.G3b(19) N'2f(17) 45.Gx2a(17) R'8i(15) +46.N'5i(6) Nx3h+(10) 47.Kx3h S'2f 48.Gx1a(8) B2g+(6) 49.K3i(1) P3f(9) +50.R1b+(4) Kx2d 51.L'2h +Bx2h(36) 52.Kx2h +B5e(4) 53.P4f(18) L'2g(3) +54.K3h(1) Lx2i+(3) 55.Px3f S2b(2) 56.B'4b(2) S3c 57.Bx5c+(5) +L2h(1) +58.Kx2h(3) +Bx4f 59.K2i +Bx3f 60.G'1d(3) +Bx1d 61.+Bx2f G'2e 62.N'3f Gx3f +63.+Rx1d Kx1d 64.+Bx3f N'2e 65.P1f(1) N'3g 66.K3h Nx4i+ 67.Px1e Resigns +# Time used black: 4.56; white: 4.59 +# +# Black: Tanigawa Koji; White: Morishita Taku. +1.P7f P8d 2.P2f(1) P8e(1) 3.B7g P3d(1) 4.S8h G3b(3) 5.G7h Bx7g+ 6.Sx7g S4b +7.S3h(1) S7b(2) 8.P4f(1) P6d(1) 9.S4g S6c 10.P6f(3) P4d(2) 11.G5h(3) G5b(3) +12.K6h(1) K4a(3) 13.K7i(1) K3a(2) 14.P3f(1) P7d(5) 15.S5f(4) S5d(1) 16.P9f +P1d(16) 17.P1f(7) P9d(10) 18.N3g(6) N7c(30) 19.P2e(21) S3c(9) 20.P4e(95) +Px4e(30) 21.P3e S4d(22) 22.P7e(17) Px7e(10) 23.P2d(1) Px2d 24.Rx2d P'2c(1) +25.R2h G6c(34) 26.B'6a(17) Px3e(12) 27.B3d+(25) S4c(5) 28.+B2e(4) B'5d(40) +29.G5h-6g(5) N3c(4) 30.+B5h(31) S3d(21) 31.R2i(5) P9e(45) 32.Px9e(54) P7f(7) +33.Gx7f(2) P'7e 34.Gx7e P8f 35.Px8f(25) P'9h(1) 36.Lx9h Bx9h+ 37.P'7d P3f(18) +38.Px7c+(3) Gx7c 39.P'7d G6c 40.N'2f S3d-3e(13) 41.P'3d(2) Px3g+ 42.Px3c+ +Gx3c(1) 43.P'3d(18) G3b(1) 44.N'5e G5d(40) 45.G8h +B9i(3) 46.K7h R9b(3) +47.P7c+(10) +P3h(26) 48.R6i(1) P'8g(6) 49.Gx8g(16) Rx9e(5) 50.+B7f(1) +N'8d(15) 51.P'9f(8) Nx7f 52.Px9e B'2e 53.P'4g(2) Sx2f 54.K6g P'8h 55.Kx7f(3) +Px8i+ 56.R'8b(2) Bx3d(2) 57.+P6c(3) P'7d(10) 58.Gx7d P'7c 59.+Px7c(8) K2b +60.N6c+(1) K3c(4) 61.K7e P'3f(3) 62.+Nx6d(1) Gx6d 63.Gx6d N'5b 64.G7d(2) K2d +65.R8a+ P3g+(3) 66.+Rx9a K3e 67.K8d(6) L'5d 68.+R4a G4c(1) 69.+Rx5b(2) Lx5f +70.Px5f S'7h 71.S8h(1) +B9h 72.L'9i +Bx8g 73.Sx8g Sx6i+ 74.P9d +Px9i 75.K8c +K3f 76.P9c+ Kx4g Jishogi. +# Black: Morishita Taku; White: Tanigawa Koji. +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.P5f(1) P5d 5.S4h S4b 6.G4i-5h(2) G3b +7.P6f K4a 8.G6g P7d(5) 9.G7h(10) G5b 10.K6i(1) S3c(3) 11.B7i(6) B3a(1) +12.P3f(1) P4d(1) 13.B6h(26) G5b-4c(13) 14.K7i(3) B6d(8) 15.N3g(2) K3a +16.K8h(7) K2b(7) 17.P2f(9) P8e(10) 18.R3h(5) S5c(10) 19.P1f(14) P1d(21) +20.P4f(20) P5e(16) 21.Px5e(30) Bx5e 22.G5f B7c(5) 23.G6e R8d(1) 24.S4g(1) +S6d(46) 25.Gx6d(17) Bx6d(2) 26.R5h(4) P'5d(10) 27.S5f(5) P7e(23) 28.Px7e(11) +Bx7e(6) 29.P'7f(12) B3a(23) 30.N2e(45) S2d(1) 31.P4e(10) Px4e(32) 32.Sx4e(44) +P'4d(10) 33.S5f P8f 34.Sx8f(22) B6d(1) 35.P'4f(1) R8b(27) 36.S'6g(4) N7c(10) +37.S7e(11) B5c(23) 38.B9e(11) B6b(1) 39.S7d(6) P'7g(13) 40.Bx7g(16) G'6d(2) +41.S7d-6e(2) Gx6e(21) 42.Px6e N8e 43.B6f(7) S'6i 44.R5i(6) Sx7h+ 45.Kx7h +B7c(7) 46.S'5g(27) P6d(24) 47.Px6d(2) Bx6d(2) 48.G'6e(18) P'7g(9) 49.Nx7g(1) +Nx9g+ 50.Gx6d Rx8g+ 51.K6i +R8h 52.S6h +N8g(1) 53.K5h(6) G'7h(1) 54.Sx7h(1) ++Nx7h 55.G'6g S'6i(15) 56.Rx6i +Nx6i 57.Kx6i +Rx9i 58.K5h(1) L'5e(4) +59.Sx5e(4) Px5e 60.L'7i(1) Sx2e(1) 61.Px2e(2) N'5f 62.Gx5f(2) Px5f 63.S'4h(1) +R'2g(3) 64.N'4g(6) S'5g(1) 65.S4hx5g(5) Px5g+ 66.Kx5g P'5e 67.B'7d(5) P'7c(1) +68.Gx7c(4) G'6d 69.N'4h(3) Gx7d(2) 70.Gx7d B'2i(3) 71.S'5h S'3h 72.Resigns. +# Black: Tanigawa Koji; White: Morishita Taku. +# +1.P7f P8d(1) 2.S6h(2) P3d(1) 3.S7g S6b(1) 4.S4h P5d(1) 5.P5f S4b 6.G4i-5h(6) +G3b(2) 7.P6f(2) K4a(3) 8.G6g P7d(2) 9.G7h(5) G5b(2) 10.K6i S3c 11.B7i(2) +B3a(7) 12.P3f(10) P4d(4) 13.S3g(9) B6d(17) 14.B6h(10) G5b-4c(8) 15.K7i(4) +K3a(1) 16.K8h P8e(11) 17.P1f(10) K2b(14) 18.P2f(7) S7c(25) 19.S4f(6) P7e +20.Px7e(23) P4e(56) 21.S3g Bx7e 22.P'7f(15) B5c(30) 23.P4f(20) Px4f(1) +24.Sx4f P'4e 25.S3g S7d(1) 26.R4h(23) P6d(44) 27.Rx4e(59) P6e(8) 28.R4g(30) +P8f(26) 29.Px8f(6) N7c(16) 30.B4f(12) R8c(1) 31.S4h P'4e(12) 32.B2h(1) +Px6f(15) 33.Gx6f(14) S6e(33) 34.S5g(43) P'8e(3) 35.G6f-6g(3) P5e(2) 36.Bx5e +Bx2f(27) 37.P'4h(31) S5d(11) 38.B2h N6e(1) 39.S5g-6f(13) Nx7g+(5) 40.G6gx7g +S'4f(2) 41.B1g(8) Sx4g=(5) 42.Bx2f Sx5f+(13) 43.B'7d(9) +Sx6f 44.Bx8c+ +Sx7g +45.Kx7g R'6i(3) 46.P'2d(2) S'6f(16) 47.K8h P'7g 48.Px2c+ Kx2c 49.N'1e(12) K1b +50.+B5f Px8f(6) 51.R'8b(1) Px7h+(2) 52.+Bx7h G'8g 53.Resigns. +# Time black: 6.38; time white: 7.19. +# +# --------------------------------------------------------------------------- +# +# 4-th Ryu O Tournament, 4-th game, 26-th & 27-th November 1991. +# +# Black: Morishita Taku; White: Tanigawa Koji. +# +1.P7f P8d 2.S6h(2) P3d(1) 3.S7g S6b 4.P5f(1) P5d 5.S4h(1) S4b 6.G4i-5h(1) +G3b(2) 7.P6f(1) K4a 8.G6g P7d(5) 9.G7h(5) G5b 10.K6i(2) S3c(3) 11.B7i(3) B3a +12.P3f(1) P4d(6) 13.B6h(5) G5b-4c(14) 14.K7i(1) S7c(7) 15.K8h(22) P9d(8) +16.P3e(27) Px3e(22) 17.Bx3e P7e 18.Px7e(9) Bx7e(1) 19.P6e(3) K3a(9) +20.R3h(24) K2b(5) 21.B4f(4) R9b(10) 22.S5g(2) B4b(4) 23.S5g-6f(1) P9e(33) +24.P1f(36) P1d(70) 25.P'7e(40) P8e(17) 26.P2f(39) S8d(14) 27.N1g(6) P4e(13) +28.B5g(9) S4d(5) 29.P4f(34) Px4f(3) 30.Bx4f P'4e 31.B6h P'3e(8) 32.S7f(4) +P2d(17) 33.P2e(12) Px2e(13) 34.P5e(11) Px5e(47) 35.B7g(5) P'7d(1) 36.Sx5e(2) +Sx5e(2) 37.Bx5e S'4d 38.B6f(3) Px7e(3) 39.P'5c(13) Bx5c(19) 40.P'5d(19) +Gx5d(1) 41.P'2d(23) K3c(22) 42.Rx3e(11) P'3d(1) 43.Rx2e P'2b(2) 44.P6d(10) +Px6d(9) 45.S'6c(3) G4c 46.Sx5d+(10) Gx5d 47.G'6c(1) B3a(5) 48.P'4b(1) Bx4b(6) +49.P'5c(5) N1c(13) 50.R2i(5) P6e(6) 51.Sx6e(14) Gx6e 52.P5b+ Gx6f(1) +53.+Px4b(11) S'2h(7) 54.Rx2h(12) Gx6g 55.B'6d(3) B'3i(7) 56.P2c+(2) Px2c +57.+P4c Kx4c 58.Rx2c+ G'3c 59.G5c Sx5c 60.Bx5c+ Kx5c 61.+Rx3c G'4c(3) +62.S'4d(2) K6b 63.G'6c(3) K7a 64.+R3a(2) P'6a 65.Gx6g(1) P8f 66.S'7d(1) +Px8g+(26) 67.Kx8g S'8c 68.Sx8c+(2) B'6e 69.K7h Bx8c 70.P'8e S'7f 71.Px8d(4) +Sx6g+ 72.Kx6g B9d 73.K5f(1) G'7b(2) 74.Gx7b(3) Rx7b 75.S'6c(1) Gx4d(3) +76.Sx7b+ Bx7b 77.S'8b(1) Resigns. +# Time black: 7.58; time white: 7.56. +# +# --------------------------------------------------------------------------- +# +# 4-th Ryu O Tournament, 5-th game, 4-th & 5-th December 1991. +# +# Black: Tanigawa Koji; White: Morishita Taku. +# +1.P7f P8d(1) 2.P2f P8e(1) 3.B7g P3d(1) 4.S8h G3b 5.G7h Bx7g+(4) 6.Sx7g S4b +7.S3h S7b(2) 8.P4f P6d(1) 9.S4g S6c 10.P6f P4d(2) 11.G5h(1) G5b 12.K6h K4a +13.K7i K3a(1) 14.P3f(3) P7d(2) 15.S5f(1) S5d(1) 16.P9f(14) P1d(7) 17.P1f(11) +P9d(6) 18.N3g(66) N7c(23) 19.P2e(33) S3c(13) 20.P4e(51) Px4e(11) 21.P3e +S4d(48) 22.P2d(3) Px2d 23.Rx2d P'2c(3) 24.R2h P6e(83) 25.Px6e(26) Nx6e(1) +26.S6f(35) B'6d(3) 27.B'5i(14) G5b-4c(10) 28.S5fx6e(13) Sx6e 29.Sx6e B5e +30.S'7g P8f(13) 31.Px8f S'3f(2) 32.G4h(5) P4f(5) 33.S5f(4) B7c 34.P'4e(13) +Sx3e(32) 35.P'6d(26) P'8g(31) 36.N'4d(9) B8d(21) 37.N2e(21) P2d(17) 38.P8e(8) +B5a(1) 39.S8f(5) Px2e(6) 40.B7g B3c(10) 41.P6c+ P2f(23) 42.Gx8g(1) P'6g(14) +43.P'2d(2) P2g+(3) 44.Nx3b+(19) Rx3b 45.P2c+ +Px2h 46.+Px3b(6) Kx3b 47.P'2d +Sx2d(1) 48.R'6b Resigns(2). +# Time black: 6.30; time white: 6.45. +# +# --------------------------------------------------------------------------- +# +# 4-th Ryu O Tournament, 6-th game, 17-th & 18-th December 1991. +# +# Black: Morishita Taku; White: Tanigawa Koji. +# +1.P7f P8d 2.S6h(2) P3d(1) 3.S7g S6b(1) 4.P5f(1) P5d 5.S4h S4b(1) 6.G4i-5h G3b +7.P6f K4a 8.G6g P7d(2) 9.G7h(6) G5b(6) 10.K6i(2) S3c(6) 11.B7i(3) B3a(1) +12.P3f(7) P4d(1) 13.B6h(11) P9d(13) 14.K7i(49) P9e(11) 15.K8h(11) L9c(21) +16.P3e(15) Px3e(40) 17.Bx3e N7c 18.R3h(68) B6d(33) 19.B4f(3) Bx4f(27) 20.Px4f +B'4i 21.R2h(1) B5h+ 22.G5g(1) +B2e(9) 23.S4g(2) P6d(1) 24.P2f(4) +B4c(2) +25.G5g-6g(1) +B4b(45) 26.N3g(42) G5b-4c(2) 27.P1f(2) P8e(14) 28.R2i(18) +K3a(17) 29.P2e(17) P6e(18) 30.Px6e(7) P8f(1) 31.Sx8f(3) Nx6e 32.B'6f(7) +R8c(3) 33.P2d(10) Px2d(12) 34.P'2e(5) P5e(24) 35.Px2d(16) Sx2d 36.P4e +P'2g(15) 37.Rx2g(38) P'8e(19) 38.Sx8e Rx8e 39.Bx9c+ P'8f(19) 40.Px8f(7) +P'8g(1) 41.Gx8g(3) +Bx8f(1) 42.Gx8f(1) Rx8f 43.P'8g S'7i(1) 44.Kx7i(14) Rx8g+ +45.K6h +R8h(17) 46.L'7h(2) +Rx8i 47.Px4d(1) G5c(59) 48.Rx2d(27) P'2c +49.S'4c(11) Px2d(7) 50.Sx3b+ Kx3b 51.S'4c Gx4c 52.Px4c+ Kx4c 53.P'4d Kx4d(1) +54.P'4e K5c(2) 55.G'4d(1) K4b 56.G'4c K5a(1) 57.G5b Kx5b 58.B'4c K5a 59.Bx6e+ +P'6f(1) 60.Resigns. +# Time black: 7.07; time white: 7.37. +# +# --------------------------------------------------------------------------- +# +# 4-th Ryu O Tournament, 7-th game, 26-th & 27-th December 1991. +# +# Black: Tanigawa Koji; White: Morishita Taku. +# +1.P7f P8d 2.S6h(1) P3d 3.S7g S6b(1) 4.S4h P5d 5.P5f S4b(1) 6.G4i-5h G3b(1) +7.P6f K4a(1) 8.G6g P7d(4) 9.G7h(20) G5b(8) 10.K6i S3c 11.B7i B3a(2) 12.P3f +P4d(3) 13.B6h(4) G5b-4c(20) 14.K7i(2) B6d(4) 15.N3g(2) K3a(4) 16.K8h(9) +K2b(2) 17.R3h(7) P8e(16) 18.P1f(14) S7c(39) 19.S5g(39) S8d(3) 20.P6e(14) +B4b(4) 21.S5g-6f N7c(17) 22.N2e(17) S2d 23.P2f P6d(30) 24.B4f(93) R6b(4) +25.Bx6d(10) Bx6d(25) 26.Px6d Rx6d 27.P9f(2) P'6e(38) 28.S5g P7e(1) 29.Px7e(1) +Sx7e 30.P'7f S8d(1) 31.B'7b(23) P8f(59) 32.Px8f(4) P'8e 33.B8c+(12) P4e(43) +34.P7e(72) Px8f(37) 35.P7d S7e(1) 36.+Bx7c Sx2e(43) 37.Sx8f(43) Sx8f(21) +38.+Bx6d S'7e 39.+Bx6e(1) P'8g(7) 40.K7i(7) Sx2f(20) 41.R'8b(2) P4f(10) +42.N'5e(13) G4c-4b(3) 43.+Bx5d P'5b 44.+Bx3b Kx3b(1) 45.G'4c K2b 46.Gx4b +P1d(2) 47.G3b(1) K1c 48.P1e Px4g+(1) 49.Px1d Resigns. +# +# + 1.P7f P8d 2.S6h P3d 3.S7g S6b 4.S4h P5d 5.P5f S4b 6.G4i-5h G3b + 7.P6f K4a 8.G6g P7d 9.G7h +[ 9.K6h now is dangerous because white can build a formation with P6d, + S6c, N7c,S4d, P8e, G5b and attack with P5e and P6e. ] + 9... S3c 10.K6i G5b 11.B7i B3a 12.P3f P4d 13.S3g B6d +[ 13... G5b-4c is playable for white but dangerous because of 14.P3e ] + 14.P6e B4b +[ 14.B6h is more common than 14.P6e. If 14... B7c? instead of 14... B4b + then 15.P7e Px7e 16.S6f R7b 17.Sx7e! Bx3g+ 18.Nx3g Rx7e 19.B'8b is + better for black.] + 15.P5e +[ This position but with a black pawn on 2f and a white one on 8e is old- + fashioned and was played some 20 years ago. Black gained nothing from + this opening, but without the exchange of P2f and P8e it is better for + black of course. ] + 15... S5c +[ 15... Px5e? 16.S4f G5b-4c 17.Sx5e P'5d 18.S5e-6f gives black a clear + positional advantage. ] + 16.R5h G3b-4c!? +[ 16... G5b-4c and 16... Px5e are found in professional games. Two weeks + before this game Morishita played 16... G3b-4c against Yonenaga. The + game continued 17.S4f P8e 18.N3g N7g 19.P7e R8d 20.S7f P6d 21.B5g Nx6e, + resulting in an equal position. ] + 17.Px5d Sx5d 18.S6f G4c-5c 19.S4f K3b +[ 19... S4c is a typical positional mistake: 20.S4f-5g K3b 21.S5f and + 22.B4f follow with a better position for black. ] + 20.P'5e S4c 21.S4f-5g P6d 22.Px6d N7c! 23.N7g Gx6d 24.P'6e G6d-6c + (equal) 25.S5f P8e 26.N3g P9d 27.P2f P9e 28.G8h P8f 29.Px8f Rx8f + 30.P'8g R8c 31.K7h L9d 32.B4f R9c 33.P5d Gx5d 34.S5f-5e Gx5e + 35.Sx5e P9f 36.Px9f Lx9f 37.P'5c Bx5c 38.Lx9f Rx9f 39.L'5d R9i+ + 40.G8i S'6i 41.Kx6i +Rx8i 42.G'7i +R9i 43.Lx5c+ Gx5c 44.S6d Gx6d + 45.Bx6d L'5d 46.S'5e +[ 46.Rx5d? Sx5d 47.G'3a K2b 48.B'3b G'7h 49.Kx7h R'8h and 46.N2e? G'5i! + 47.K7h S'6i 48.Gx6i +Rx6i 49.K8h +Rx5h 50.S'6h G'7h both lead to mate. ] + 46... P'5g 47.Rx5g S'8h?? +[ 46... S'4i is another winning possibility. 47... L'7h instead of S'8h + leads to a certain win for white: 48.Kx7h S'8h and now a) 49.L'8i Sx7i+ + 50.Kx7i G'8h, b) 49.B'6h Lx5e 50.Rx5e P'5d or c) 49.G6i +R9h. ] + 48.N2e +Rx7i 49.K5h G'4a 50.B'6c G'5b? +[ According to "Shukan Shogi" Habu still had chances to keep fighting + after 47... S'8h??, but 50.G'5b seems the same as resigning. After + 50... L'5b 51.Sx5d Sx5d 52.Rx5d S'4c! the situation is still unclear. + Moreover, Tanigawa's king is in a very bad position. ] + 51.Sx5d Gx6c 52.Sx4c+ Kx4c 53.Nx3c+ Kx3c 54.S'4b Gx4b + 55.Bx4b+ Kx4b 56.G'3b Resigns. +# Time used: Black 7:31, White 7:58. +# +# ----------------------------------------------------------------------- +# +# Ryu O Title Match 1990, Game 2: Habu Yoshiharu - Tanigawa Koji. +# 31 October & 1 November 1990. Comment by Katsuhiko Murooka. +# + 1.P7f P8d 2.S6h P3d 3.S7g S6b 4.P5f G3b 5.S4h K4a 6.G4i-5h G5b + 7.P6f P6d 8.P2f S4b 9.G6g P7d 10.G7h S6c 11.K6i N7c 12.P2e S3c + 13.B7i P8e 14.P3f P5d 15.S3g +[ Alternatives are 15.P4f or 15.P3e Px3e 16.Bx3e S4d and now e.g. + a) 17.P2d? Sx3e! 18.Px2c+ B4d 19.+Px3b Kx3b 20.P'3c Nx3c 21.G'2b K4a!, + which is very good for white, Takahashi - Y. Sato 0-1, 1988 or + b) 17.B6h P5e 18.Px5e P6e 19.P2d Px2d 20.P'2c Gx2c 21.Bx2d K3b, + unclear, Y. Sato - H. Nakada 1-0, 1988. ] + 15... S4d 16.P2d Px2d 17.Bx2d P'2c 18.B1e P6e +[ 18... P5e? 19.Px5e P6e and a) 20.B2f P3e 21.S4f Sx5e 22.Sx5e Bx5e + 23.S'4f B2b 24.Bx3e or b) 20.S4f Sx5e 21.Sx5e Bx5e 22.B3g Bx3g+ + 23.Nx3g. Both variations favour black. ] + 19.Px6e Nx6e 20.S6f P'6d +[ 20... S5c 21.P'2d Px2d 22.P'2c B4d 23.Bx2d P8f 24.B4f P'6d 25.Px8f P7e + gives black a small edge, Morishita - Moriuchi 1-0, 1988. ] + 21.S4f P8f 22.Px8f Rx8f 23.P'8g R8a 24.B2f P1d 25.P1f +[ 25.N3g P3e 26.Sx3e Sx3e 27.Bx3e B4d 28.Bx4d Px4d 29.Sx6e Px6e 30.P'6d + is good for black, Takahashi - Tanigawa 1-0, 1988 or 25.K7i P2d?! + 26.P1f G2c 27.B5i P9d 28.P9f K3b 29.B6h gives black a slightly better + position, Y. Sato - Murayama 1-0, 1990. ] + 25... P9d 26.P9f (adjourned) +[ My opinion of the adjourned position is that black stands a bit better. ] + 26... P2d 27.K7i G2c 28.B5i K3b 29.B6h B3c 30.K8h B5a 31.P3e Px3e + 32.Sx3e Sx3e 33.Bx3e P'8f +[ After 33... P'3d 36.B6h B3c 35.P5e P7e 36.P'2e Px2e 37.N3g black + stands slightly better, Y. Sato - Murayama 1-0, 1990. ] + 34.Px8f P'8e 35.R3h +[ 35.Px8e?? Rx8e 36.P'8f N7g+ followed by 37... Rx3e and white wins. ] + 35... B3c 36.Px8e S'2g 37.R3g S2h= 38.R3f Sx1i+ 39.B6h +Sx2i + 40.P'2e N'5g! 41.S'3e?! +[ After 40.N'5g the position is unclear, although black still has a + slight edge. 41.S'3e is inaccurate, however, and should have been + 41.P5e.] + 41... N6i+ 42.B8f L'8c 43.Px2d G2b 44.N9g P9e 45.Px9e P7e + 46.S3d Bx2d 47.P'2c?! +[ 42.R2f P'2d 43.Rx2i is better. ] + 47... G3c 48.P2b+ K2b 49.Sx3c Bx3c 50.P'2d P'9f 51.G'2c? +[ I think 51.R2f Bx2d 52.Rx2d P'2c 53.Rx2i is better than what happened + in the game. ] + 51... K3a 52.Gx3c Px9g+ 53.Lx9g +[ According to "Shukan Shogi" and the TV program "Go & Shogi weekly" + Habu's 53.Lx9g was the losing move. Habu should have played 53.Kx9g + followed by 53... Nx3c 54.Rx3c+ P'3b 55.N'2c K4a 56.+R2b with chances + for both players. ] + 53... Nx3c 54.P2c+ P'3b 55.B'2d G4b! 56.+Px3b Kx3b 57.P'3d P'3e + 58.Rx3e S'4d 59.Px3c+ Sx3c 60.Bx3c+ Gx3c 61.P'3d G2c 62.P'2d P'8g + 63.Kx8g Lx8e 64.Px2c+ K4a 65.Sx7e Lx8f 66.Sx8f Rx8f 67.Kx8f N'7d + 68.Resigns. +# Time used, black: 7:38, white 7:35. +# +# ----------------------------------------------------------------------- +# +# Ryu O Title Match 1990, Game 3: Tanigawa Koji - Habu Yoshiharu. +# 8 and 9 November 1990. Comment by Katsuhiko Murooka. +# + 1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S4b + 7.S3h S7b 8.P4f P6d 9.S4g S6c 10.G5h G5b 11.K6h K4a 12.S5f S5d + 13.P6f P4d 14.P3f P7d 15.K7i K3a 16.N3g P1d 17.P1f G5b-4c + 18.K8h P9d 19.P9f S3c 20.R4h K2b 21.P4e +[ Alternatives: + --21.B'2h!? S4b 22.P6e Sx6e 23.Sx6e Px6e 24.P4e S'2g 25.Px4d G4c-3c + 26.N2e Sx2h= 27.Nx3c+ Nx3c 28.S'4c P'4e 29.Sx3b+ Kx3b 30.P3e S3g+ + 31.R4i N'8f (slight advantage white), Maruta - Nakahara 0-1, 1986. + --21.L1h!? G4c-4b 22.B'1i!? B'2g 23.G4g P1e 24.N2e Px1f 25.P4e P1g+ + 26.Bx6d R9b 27.Nx3c+ Kx3c 28.Px4d Bx1h+ 29.P'1b Lx1b 30.Rx1h+ +Px1h + 31.B'1a (slight advantage black, but what if 21... K3a!), Tanigawa - + Nakahara 1-0, 1986. ] + 21... Px4e 22.B'4a S4d +[ 22... B'9b? 23.Sx4e Sx4e 24.Nx4e S4d 25.B6c+ and black stands better, + after 22... R7b black would have the better position, too. + 22... P1e!? 23.Px7e P6e 24.Px6e P4f 25.B1d+ R6b is unclear. Maybe white + stands a bit better, Tanigawa - T. Tanaka 1-0, exhibition game 1986. + 22... P7e!? 23.B7d+ Px7f 24.Sx7f P6e 25.P1e Px1e 26.+B6d P'7c 27.P'1c + and black stands slightly better, Morishita - Oshima 1-0, 1990. ] + 23.Bx7d+ P3e 24.+Bx6d B'7c 25.+Bx7c Nx7c 26.B'6d R8c + (26... R7b?!) 27.Sx4e +[ If 27.Nx4e then 27... P'4f 28.Bx4f P4e 29.Px9e S5dx4e 30.Sx4e. White + stands slightly better, Maruyama - Senzaki 0-1, 1990. ] + 27... S5dx4e 28.Nx4e P8f 29.Px8f (adjourned) +[ My opinion of the adjourned position is that black stands a bit better, + but probably Habu has prepared something new for this game, because if + he picked out this system for white, the adjourned position could + hardly be avoided.] + 29... P'4g 30.Rx4g B'3h 31.R4h B7d+ 32.S'5e! S'5d! 33.Sx4d +Bx6d + 34.Nx5c+ Gx4d 35.Rx4d +Bx5c 36.R4a+ S'6i 37.G5h-6h Sx7h+ + 38.Gx7h N'8e 39.G'8g?! +[ With 39.G'8g black loses his advantage. 39.S'8g would have been better. + According to Kato Hifumi on the television program "Go & Shogi Weekly" + after 32.G'8g white stands a bit better.] + 39...G'3a 40.+Rx9a Nx7g+ 41.G8gx7g S'6i 42.S'8g N6e! 43.Px6e Sx7h+ + 44.Kx7h +[ If 44.Sx7h then 44...G'6h which is good for white, or if 44.Gx7h?? then + 44... B'5e and white will win.] + 44... +B4d (Sx6e!? is possible, too) 45.L'4i +[ Allowing 45... R4c would be decisive. ] + 45... +B5e 46.+Rx9d R6c 47.S'5f Rx6e 48.P'6g! P'6f 49.Px6f Rx6f + 50.Sx5e G'6h 51.K8h B'7i 52.K9h P'9g 53.Nx9g Sx5e 54.S'8i R6g+?? +[ 54... G6g 55.Gx6f Sx6f 56.B'4d S'3c 57.Bx6f Gx6f. This position is + unclear, but I would prefer to play the white side after 54... G6g.] + 55.Gx6g Gx6g 56.R'6a S'7h 57.Rx3a+ Kx3a +[ 57... Gx3a 58.N'3d and now 58... K1c 59.N'2e K2d 60.N4b+ G'4d 61.+Rx4d + Sx4d 62.G'3d leads to mate, or 58... K1b 59.G'2b K1c 60.N'2e K2d + 61.B'5a G'3c 62.Gx2c Kx2c 63.Nx3c+ Nx3c 64.Bx3c+ Kx3c 65.+R8c and mate + follows soon, too. ] + 58.B'5c K2b 59.N'3d Resigns. +[ 59... K1c 60.N'2e K1b 61.G'2b Gx2b 62.Nx2b+ Kx2b 63.+R9b and black + wins. ] +# +# ----------------------------------------------------------------------- +# +# Ryu O Title Match 1990, Game 4: Habu Yoshiharu - Tanigawa Koji. +# 15 and 16 November 1990. Comment by Katsuhiko Murooka. +# + 1.P7f P8d 2.P2f P8e 3.B7g P3d 4.S8h G3b 5.G7h Bx7g+ 6.Sx7g S4b + 7.S3h S7b 8.P4f S3c 9.S4g K4b 10.G5h S8c 11.P6f S8d 12.P9f (black + must not allow 12... S9e) P7d +[ In professional play 12... P9d 13.P3f P7d occurred many times. Instead + of 13... P7d has also been played: 13... P9e 14.Px9e Sx9e 15.Lx9e Lx9e + 16.P'9g P'9h 17.S8h L'9a 18.N3g P8f 19.Px8f Rx8f 20.N7g (slightly + better for black), Yonenaga - Minami 1-0, 1990 or 13... K3a 14.N3g G5b + 15.K4h P6d!?/?!, Tanigawa - Nakahara 0-1, Meijin title game 6, 1990. ] + 13.S5f P7e 14.P4e +[ 14.S6e or 14.S6g are solid and give black the better position, but Habu + wanted more. ] + 14... Px7f 15.Sx7f K3a 16.P'7e S7c 17.B'4f B'6d +[ The only move: 17... S6d?? 18.P6e S7c 19.P7d or 17... P6d 18.P7d Sx7d + 19.Bx6d. ] + 18.S5e Bx5e 19.Bx5e S6d 20.B4f +[ 20.Bx3c+?! Nx3c allows white to seize the initiative. ] + 20... S'5e (adjourned) +[ Time used: black 4:27, white 3:09. I think Habu made a wise decision to + seal here and not to play the obvious move 21.Bx5e. In the second + session Tanigawa must take the bishop anyway, so Habu has some extra + thinking time until the next morning. This decision cost him 36 + minutes, however, since he had to wait so long before he could seal. + My opinion of the adjourned position is that black stands a bit better. ] + 21.Bx5e Sx5e 22.S'7g P4d 23.Px4d S5ex4d 24.K6h P'7c +[ Why not 24.P7d? After 24... P'7c the position is balanced. On 20-th + November, I met Mr. Habu and asked him: "Why didn't you play 24.P7d?". + He replied: "I wanted to play 25.P7d after 24.K6h and didn't think that + Mr. Tanigawa would play P'7c so soon". ] + 25.G7h-6g K2b 26.K7h G5a 27.P2e S3e 28.G5f R4b 29.P'4e P'4d + 30.Px4d S3ex4d 31.B'6e B'6a +[ 31... S4e?? 32.P'4c. 31... R8b? 32.P'4e S3e 33.G4g favours black. ] + 32.S6g S4e 33.Gx4e Rx4e 34.B3h R4b 35.P9e P3e 36.P'4g P1d + 37.P1f B3d 38.P5f P5d 39.B2g P'4f 40.Px4f Rx4f 41.P3f +[ 41.P'4g? R2f strongly favours white. ] + 41... Bx2e 42.Px3e B3f! +[ now white stands slightly better ] + 43.P3d S4d 44.P3c+ Sx3c 45.Bx3f Rx3f 46.P'3g R4f 47.P'4g R4b + 48.B'5c R4a 49.B3e+ (49.B7a+? G5b) P'3h 50.Rx3h B'2g 51.R2h B4i+ + 52.N1g +B3i 53.R2f P'3d 54.+B5c G'3e 55.R2g +B3h 56.P'2h P'4f + 57.Px4f Rx4f +[ White stands clearly better now.] + 58.P'4g +Bx4g 59.+Bx6c G5a-4b (time 7:07 - 7:21) + 60.+Bx8a +B3h?!/!? +[ Tanigawa wants to play 62.P'5g. 60... +B3h induces black to play + 62.+Bx5d, after which white can play 62... P'5g. ] + 61.P'4g +Bx4g 62.+Bx5d +[ 62.+Bx9a would meet 62... +B3h again, but now black does not have a + pawn in hand ! ] + 62... P'5g 63.Gx4g Rx4g+ 64.B'7f +R4h 65.S'6h G'5c (7:19 - 7:40) + 66.+B8a P'4f 67.P3f P4g+ 68.P'4i +R3h 69.Rx4g? +[ Black should have fought for a draw and played the following line: + 69.Px3e P5h+ 70.N2e +Px6h 71.Sx6h S'5g 72.Nx3c+ Nx3c 73.S'7i ] + 69... +Rx4g 70.Px3e +Rx4i 71.+B2g +Rx1i 72.N'4e R'3i 73.P'4i L'2d + 74.Px3d Sx3d 75.Nx5c+ Lx2g+ (7:37 - 7:46) 76.+Nx4b Gx4b + 77.Px2g Rx4i+ 78.L'5i B'3g? +[ After 78... +R2h white would have a won position. ] + 79.P'3e S4c 80.G'6i N'8d? 81.B6e P'6d? 82.B8c+ P'4g 83.G'3f Bx5i+ + 84.Gx5i +Rx5i 85.Sx5i +Rx5i (7:46 - 7:56) 86.G'6i +R4h + 87.R'6h L'8a 88.+Bx8d! Lx8d +[ the position is equal now ] + 89.B'5e P'3c 90.Rx4h Px4h+ 91.N'3d Sx3d 92.Px3d B'5d (7:51 - 7:59) + 93.Px3c+ Nx3c 94.S'3a Kx3a 95.R'5a P'4a 96.Rx5d+ +P5h 97.B'2b!! +[ 97.P'3d?? +Px6i 98.B'2b K2a or 97.P'4c? G3b 98.Bx3c+ Gx3c 99.N2e R'4h + and in both cases white will win. ] + 97... Kx2b (7:58 - 7:59) 98.P'3d R'4h +[ 98... +Px6i?? 99.Px3c+ Gx3c 100.Bx3c+ Kx3c 101.N2e K3b 102.+R5b G'4b + 103.G'3c K2a 104.N'1c Lx1c 105.Nx1c= K1a 106.L'1b Kx1b 107.+Rx4b Px4b + 108.G'2b Kx1c 109.G2bx2c mate. ] + 99.Px3c+ Gx3c 100.Bx3c+ Kx3c 101.N2e K3b 102.Sx5h! Resigns +[ 102... Px5h+ 103.P'3c K2a 104.G'3b K1b 105.+Rx1d mate. ] +# (7:59 - 7:59) +# What a tough game ! +# +# ----------------------------------------------------------------------- +# +# Ryu O Title Match 1990, Game 5: Tanigawa Koji - Habu Yoshiharu. +# 26 and 27 November 1990. Comment by Katsuhiko Murooka. +# + 1.P7f P3d 2.P2f P4d 3.P2e B3c 4.S4h S3b 5.P5f R4b +[ A surprising opening. Four days before this game Habu played this + opening against Katsuura and he won. On the other hand, one might + suppose that Habu could not find a good way against the bishop exchange + opening. ] + 6.K6h K6b 7.K7h K7b 8.G4i-5h G4a-5b 9.P9f P9d 10.S5g K8b + 11.P8f S4c 12.K8g S7b 13.S7h P6d 14.S6f G6c +[ This seems rather old-fashioned. 14... S5d is fashionable nowadays. ] + 15.S6f-7g P6e 16.B7i R2b 17.P6f Px6f 18.G5g P7d 19.Gx6f N7c + 20.P3f P'6e 21.G6g P5d +[ For the variations 21... P4e and 21... P8d, refer to my book "4-th file + rook opening II" (pages 74-79; both his books on the 4-th file rook are + really good/PS). 21... P5d is the latest move and I think it is better + than both 21... P4e and 21... P8d. ] + 22.B4f B4b 23.P'6f P4e +[ 23... Px6f 24.Sx6f P'6d 25.N7g P8d? 26.P7e! S8c 27.Px7d Sx7d 28.P'7e + favours black, Murooka - Kikuchi 1-0, 1990. ] + 24.B3g P3e!? 25.Px3e Px6f 26.Sx6f P'3f 27.B5i +[ Adjourned. My opinion of the adjourned position is that it is slightly + better for black. ] + 27... R3b 28.P2d Px2d 29.N7g P8d 30.P'6e S5b 31.P5e Rx3e + 32.Px5d P3g+ 33.Bx3g P4f 34.Px4f N3c 35.P'3f +[ 35.Rx2d R2e 36.Rx2e Nx2e 37.R'2b Nx3g= 38.Rx4b+ P'4a favours white. ] + 35... Rx3f 36.Rx2d P'6h! 37.G6gx6h +[ The position is equal now. 37.G7i and 37.G6ix6h will meet 37... N4e + 38.R2b+ B3c 39.+Rx3c Rx3c 40.Px4e R'4i, which favours white. ] + 37... N4e 38.R2b+ P'4a +[ 38... B3c? 39.+Rx3c Rx3c 40.Px4e strongly favours black. ] + 39.Px4e Rx6f 40.G6g Rx6g+ +[ 40... R3f 41.N'6d would favour black. ] + 41.Sx6g P'5f 42.Sx5f P7e 43.N'6d +[ If 42... G'6f?? instead of 42... P7e then 43.S5e and black will win. If + 43.Px7e? instead of 43.N'6d then 43... Bx7e favours white. ] + 43... G'6f 44.Nx7b+ Gx7b 45.S'6g S'5g 46.P6d!! +[ A very strong, but double-edged move. Who dares to play this move in + such a big title match game ! I suppose Habu may have been surprised. ] + 46... Px7f 47.Sx7f Gx6d 48.Bx6d +[ 48.+Rx4b?? Px4b 49.Bx6d Gx7f 50.Kx7f R'6f and white will win. Tanigawa + played 48.Bx6d instantly. ] + 48... Bx6d 49.+Rx5b B'2e? +[ After 49.+Rx5b, Habu spent all his remaining time on his next move, but + he had only 18 minutes. 49.B'7d would have given him some chances: + 50.+R6a? Gx7f 51.Kx7f S'7e 52.K6g S5g-6f+ 53.K5h P'7a is good for + white, but 50.S'7a Kx7a 51.R'6a K8b 52.+Rx7b (52.Rx6d+?? Bx5b and white + will win) Kx7b 53.Rx6d+ and now: A) 53... Gx7g 54.Kx7g N'6e 55.K8h S'7g + 56.K9g and there is no mate or B) + 53... N'9e 54.Px9e Gx7g 55.Kx7g N'6e 56.K8g R'7g 57.K8h and black will + win, too. ] + 50.S'7a K9c +[ 50... Kx7a 51.R'6a K8b 52.Rx9a+ Kx9a 53.G'9b and mate follows. ] + 51.+Rx7b Gx7f 52.Kx7f S'7e 53.K6g S7e-6f 54.K7h Bx6i+ + 55.K8i Resigns +# Black: Habu Yoshiharu, challenger; White: Tanigawa Koji, Ryu-O +1.P2f(1) P8d 2.P2e(1) P8e 3.G7h G3b 4.P2d(1) Px2d 5.Rx2d P'2c 6.R2f S7b(3) +7.S3h(2) P6d(12) 8.P1f(8) P1d(17) 9.P7f(3) P8f(7) 10.Px8f(2) Rx8f 11.P'8g(15) +R8b(20) 12.P4f(5) S6c(3) 13.S4g(2) S5d(4) 14.S5f(3) P3d 15.G4h(21) G5b(2) +16.P3f(6) P4d(14) 17.S6h(11) S4b(4) 18.K5h(9) S6e(12) 19.Sx6e(30) Px6e(2) +20.N3g(1) S4c(20) 21.P5f(7) P'8f(18) 22.Px8f(7) Rx8f(3) 23.S7g(11) R8b 24.P'8g +B1c(10) 25.P1e(32) Bx4f(18) 26.S'5g(2) B2d(28) 27.Px1d P'1e 28.P7e(12) +Lx1d(20) 29.P7d(2) Px7d(28) 30.S7f S5d(2) 31.P'7b(18) Rx7b(11) 32.P5e(6) +S6c(1) 33.Sx6e N3c(52) 34.P5d(27) Px5d(3) 35.Bx4d(2) S'5e(39) 36.P'5c(28) +Sx4d(21) 37.Px5b+ Kx5b 38.S6e-5f(34) P'4f(3) 39.P6f(11) P5e(2) 40.S6g(1) +G4c(1) 41.N7g(3) P'6d(11) 42.P6e(2) G5d(7) 43.Px6d(33) Sx6d 44.P'6c(1) K5c(8) +45.K6i(27) P7e(4) 46.P'4e(2) Nx4e(10) 47.Nx4e(4) Sx4e 48.N'3g S5f +49.S5gx5f(11) Px5f 50.S'4e(1) P4g+(1) 51.Gx4g(5) N'5g(9) 52.K7i(24) P7f +53.Sx7f(1) Rx7f 54.Sx5d(2) Kx5d 55.P'5e Sx5e(8) 56.Rx2d(1) Px2d 57.B'6e K6d(2) +58.Bx7f(7) S'6h 59.K8i(11) P'8h(1) 60.Gx8h R'7i 61.K9h S'8i 62.Gx8i Rx8i+ +63.Kx8i S'8h 64.Resigns +# Time used black: 7.32; white: 7.22 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 2-nd game, 29-th and 30-th October 1992 +# +# Black: Tanigawa Koji, Ryu-O; White: Habu Yoshiharu, challenger +# +1.P7f P8d(1) 2.S6h(1) P3d 3.S7g S6b 4.P5f(1) P5d(1) 5.S4h S4b(1) 6.G4i-5h(1) +G3b(2) 7.P6f(1) K4a(1) 8.G6g P7d(7) 9.G7h(10) S6b-5c(28) 10.P2f(13) P5e(3) +11.Px5e(11) Bx5e(1) 12.P2e S5d(1) 13.P2d(7) Px2d(4) 14.Rx2d P'2c(1) 15.R2h +R5b(3) 16.K6i(10) B8b(84) 17.S6h(13) S3c(22) 18.S6h-5g(17) G5a(7) 19.P4f(33) +K3a(4) 20.S4g(3) G5a-4b(3) 21.P9f(3) P9d(3) 22.S4g-5f(59) K2b(64) 23.P1f(43) +P4d(7) 24.P'5e(15) Sx5e(10) 25.Sx5e(1) Bx5e 26.P'5f B7c 27.S'8c(3) P9e(6) +28.Sx7d+(10) Px9f(2) 29.P'9h(17) B8b(23) 30.+Sx6c(5) R5a(1) 31.P6e(33) P8e(7) +32.P6d(11) B9c(38) 33.+S6b(11) R5d 34.P6c+ P4e 35.P5e(17) R9d(9) 36.P'6f(4) +R4d(14) 37.Px4e(21) Rx4e 38.P'4f Rx5e 39.S5f R5d(1) 40.S4e S'5h(6) 41.K6h(9) +Sx6g+(2) 42.Gx6g R8d 43.B7g(10) P'4d(24) 44.S5f P8f 45.Px8f(5) P'8h 46.P'5c +G3a(6) 47.P5b+ G4b-3b 48.+P6c-5c(1) Px8i+(5) 49.S'4c B8b(3) 50.Sx3b+(19) Gx3b +51.G'4c G'3a 52.Gx3b(1) Gx3b 53.G'4c G'3a 54.Gx3b Gx3b 55.G'4c G'3a 56.Gx3b +Gx3b Sennichite +# Time used black: 6.59; white: 6.45 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 2-nd game replay, 10-th and 11-th November 1992 +# +# Black: Habu Yoshiharu, challenger; White: Tanigawa Koji, Ryu-O +# +1.P7f P8d(1) 2.S6h P3d 3.P6f(1) S6b(1) 4.P5f(2) P5d(1) 5.S4h(1) S4b(1) +6.G4i-5h(2) G3b(5) 7.G6g(1) K4a(1) 8.G7h(5) G5b(15) 9.K6i(1) S3c 10.S7g(1) B3a +11.B7i(1) P4d 12.P3f(2) P7d(5) 13.B6h(29) G5b-4c(12) 14.K7i(8) B6d(3) +15.N3g(3) K3a 16.R3h(7) P8e(9) 17.P2f(17) K2b(3) 18.P1f(3) S5c(31) 19.S5g(13) +P1d(76) 20.P6e(9) B7c 21.S5g-6f(1) B8d(9) 22.B4f(13) B7c(5) 23.B5g(96) R6b(37) +24.P7e Bx3g+(18) 25.Rx3g(66) N'4e 26.R3h(2) Nx5g+ 27.Gx5g(6) P6d(13) 28.Px7d +Px6e(5) 29.S7e S6d(8) 30.Sx6d(12) Rx6d 31.B'8b(8) Rx7d(1) 32.Bx9a+ P'7f(32) +33.S6h(1) S'7g(45) 34.Nx7g(14) Px7g+ 35.Sx7g N'6f(1) 36.P'7e(36) Nx7h+(31) +37.Rx7h(27) R7a(10) 38.S'7f(1) G'6f(4) 39.Gx6f(5) Px6f 40.Sx6f(4) N7c(7) +41.+B8b(4) R6a 42.S'7g(6) Rx6f(17) 43.Sx6f S'6e 44.S7fx6e(20) Nx6e 45.L'6i +P'7g(10) 46.Sx7g Nx7g+ 47.Rx7g B'9e 48.S'7h(2) Bx7g+(5) 49.Sx7g P8f +50.Sx8f(10) R'4h 51.G'7h(1) Rx4g+(12) 52.B'7f(11) P'6h(5) 53.Lx6h(1) +Rx5f +54.S7g(2) +R5i 55.P'6i(1) S'5h 56.Bx5h +Rx5h 57.S'6g(5) +R4i 58.P1e(1) B'4g(7) +59.P'5h S'5f(4) 60.Px1d(11) Sx6g+ 61.Lx6g Bx5h+ 62.G6h G'8i(8) 63.K7h(1) +P'7f(1) 64.S'1c(1) Lx1c(2) 65.Px1c+ K3a(3) 66.R'6a(2) S'4a 67.Kx8i(1) +Bx6h(2) +68.+B6d(1) G3b-4b(2) 69.+Bx4b(2) Kx4b 70.Rx4a= Kx4a 71.G'5b Kx5b 72.N'6d K4b +73.Resigns +# Time used black: 7.59; white: 7.48 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 3-rd game, 19-th and 20-th November 1992 +# +# Black: Tanigawa Koji, Ryu-O; White: Habu Yoshiharu, challenger +# +1.P7f P8d 2.S6h(1) P3d 3.P6f S6b(3) 4.P5f P5d(1) 5.S4h(1) S4b(1) 6.G4i-5h(2) +G3b 7.G6g(1) K4a(1) 8.G7h G5b(4) 9.K6i(1) S3c(3) 10.S7g(1) B3a(1) 11.B7i(1) +P4d(5) 12.P3f G5b-4c(3) 13.S3g(39) P8e(28) 14.P3e(97) Px3e(7) 15.Bx3e P4e(1) +16.K7i S5c(7) 17.K8h S5c-4d(2) 18.B6h B5c(46) 19.R4h(7) S3d(2) 20.P'3f(2) +K3a(3) 21.P4f(18) Px4f(4) 22.Sx4f P'4e 23.S3g K2b(23) 24.P1f(22) P9d(18) +25.P1e(9) P9e(7) 26.S2f(13) P7d(63) 27.N3g(18) B6d 28.R1h(9) G4c-3c(4) +29.P5e(86) Bx5e(6) 30.G5f B7c 31.P3e(1) S4c(1) 32.Nx4e G2d(1) 33.P'4f(1) +P6d(26) 34.R3h(18) B8d(5) 35.S3g(7) Gx3e(1) 36.S3f(7) Gx3f(6) 37.Rx3f P'3c(13) +38.R3g(5) S'6i(13) 39.G'6c(3) Sx7h+(24) 40.Kx7h P5e(17) 41.G5g P6e 42.N5c+(1) +Sx5c(5) 43.Gx5c P5f(2) 44.Gx5f(28) Px6f 45.P'6g N'6d(8) 46.G6e(15) P'5g(10) +47.Gx6d(24) P5h+ 48.S'4a +Px6h(32) 49.Sx6h Px6g+ 50.Rx6g P'6f(12) 51.R3g +B'5f(2) 52.P'6g G'5g(2) 53.Sx5g(10) Px6g+ 54.K8h Bx5g+ 55.Gx4c +B7i 56.Resigns +# Time used black: 7.30; white: 7.03 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 4-th game, 2-nd and 3-rd December 1992 +# +# Black: Habu Yoshiharu, challenger; White: Tanigawa Koji, Ryu-O +# +1.P7f(1) P8d(1) 2.S6h(3) P3d 3.P6f(1) S6b 4.P5f P5d 5.S4h(2) S4b 6.G4i-5h(2) +G3b 7.G6g(3) K4a 8.G7h(4) G5b(3) 9.K6i(4) S3c(1) 10.S7g(1) B3a(2) 11.B7i(2) +P4d 12.P3f(2) G5b-4c(9) 13.B6h(3) P7d(19) 14.K7i(2) B6d(6) 15.S3g(25) K3a(36) +16.K8h(3) P8e 17.P2f(5) K2b(1) 18.P1f(2) S5c(32) 19.P1e(16) P9d(4) 20.L1h(29) +P9e(40) 21.R3h(38) S5c-4b(26) 22.S4f(13) N7c(65) 23.N3g(4) S2d(13) 24.N2e(42) +P4e 25.S3g(36) N3c(11) 26.P4f(19) Nx2e(34) 27.Px2e(1) Sx2e 28.R2h(23) Px4f(23) +29.P6e(5) Nx6e(14) 30.Rx2e Nx7g+ 31.Bx7g N'3c 32.R6e(27) P4g+ 33.S2f(2) +P'4d(10) 34.P3e(1) P9f 35.Px9f(12) P'9h 36.Lx9h(5) P'9g 37.Lx9g(1) Bx9g+(1) +38.Nx9g(10) L'6d 39.Rx6d(2) Px6d 40.B'7c(36) R9b(1) 41.L'9e(2) R7b 42.Bx9a+(1) ++P5g(32) 43.Gx5g P7e 44.Px7e(1) R'2h(9) 45.S'7f(30) Rx1h+(4) 46.+Bx6d(5) +L'6a(2) 47.P'6c S5c 48.+B4f Lx6c 49.P'6e +R2i(12) 50.Px3d(7) N4e(14) +51.+Bx4e(2) Rx7e(2) 52.Sx7e(2) P'7f 53.N'2d(7) S'9i(8) 54.K9h Px7g+ 55.Nx3b+ +Kx3b 56.R'3c(1) Gx3c 57.Px3c+ Kx3c 58.L'3g Resigns +# Time used black: 7.25; white: 7.22 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 5-th game, 14-th and 15-th December 1992 +# +# Black: Tanigawa Koji, Ryu-O; White: Habu Yoshiharu, challenger +# +1.P7f P8d(2) 2.P2f G3b(2) 3.G7h(2) P8e(5) 4.B7g(2) P3d 5.S8h Bx7g+(3) 6.Sx7g +S4b(1) 7.S3h S7b(2) 8.P4f(2) P6d(15) 9.S4g(8) S6c 10.P6f(9) P1d(26) 11.P1f(11) +P9d(3) 12.P9f(5) S5d 13.S5f(1) P4d(4) 14.G5h(35) G5b(8) 15.K6h(10) K4a(2) +16.K7i(1) P7d(2) 17.P3f K3a(2) 18.N3g(22) N7c(19) 19.P2e(7) S3c(23) 20.P4e(28) +Px4e(19) 21.P3e S4d(5) 22.P7e(16) Px7e(5) 23.P2d Px2d(1) 24.Rx2d P'2c(2) +25.R2h G6c(16) 26.B'6a(54) B'4c(7) 27.Bx4c+(64) Sx4c(1) 28.P'7d Gx7d(2) +29.Nx4e P6e(45) 30.Px3d(2) P8f(39) 31.Px8f(13) B'3g(3) 32.R2i B6d+(1) +33.B'3c(59) P7f(5) 34.Sx7f(2) P'8h(35) 35.Bx1a+(8) Px8i+(1) 36.K6i +Bx8f(12) +37.P'8c(2) P'7g(40) 38.G7h-6h(22) +P7i(17) 39.K5i(14) P7h+(7) 40.Px8b+(4) ++Px6h 41.Gx6h N'3f(2) 42.R'6a P'4a(3) 43.K5h(25) +Bx7f(4) 44.K4g S3e(2) +45.+B5e(4) G'4h(1) 46.K3g +B4i 47.Resigns +# Time used black: 7.12; white: 6.34 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 6-th game, 24-th and 25-th December 1992 +# +# Black: Habu Yoshiharu, challenger; White: Tanigawa Koji, Ryu-O +# +1.P7f(1) P8d 2.S6h(2) P3d 3.P6f S6b(1) 4.P5f(1) P5d 5.S4h(2) S4b 6.G4i-5h(4) +G3b 7.G6g(1) K4a(1) 8.G7h(3) G5b(1) 9.K6i(1) S3c(2) 10.S7g(2) B3a(2) 11.B7i(1) +P4d 12.P3f(2) G5b-4c(9) 13.B6h(3) B6d(26) 14.S3g(11) P7d(3) 15.K7i(5) K3a(1) +16.K8h(1) P8e(20) 17.P1f(28) K2b(2) 18.P2f(55) P7e(27) 19.Px7e(10) Bx7e(2) +20.S4f(14) P4e(53) 21.S3g B6d 22.P4f(83) Px4f(3) 23.Sx4f(1) P'4e(38) 24.S3g +S5c 25.P1e(3) S5c-4d(25) 26.R1h(1) R7b(3) 27.S4h(10) P4f(26) 28.P6e(55) B8b(4) +29.N1g(1) S2d(37) 30.N2e(9) P8f(2) 31.Px8f(16) P4g+(16) 32.Sx4g(16) B3g+ +33.B4f P'8g(18) 34.K9h(2) +Bx4g(37) 35.Bx9a+ Sx2e 36.+Bx8a R7e(1) 37.P'4e(32) ++B6i(20) 38.Px4d(17) S'5h 39.Rx5h(32) +Bx5h 40.Px4c+(2) +Bx6g(3) 41.G'7i(7) +Rx7g+(4) 42.Nx7g(1) R'8h 43.G7ix8h Px8h+ 44.Kx8h G'8g 45.Resigns +# Time used black: 7.32; white: 6.27 +# +# --------------------------------------------------------------------------- +# +# 5-th Ryu-O Title Match, 7-th game, 5-th and 6-th January 1993 +# +# Black: Habu Yoshiharu, challenger; White: Tanigawa Koji, Ryu-O +# +1.P7f(2) P8d(1) 2.G7h(5) G3b(11) 3.B7g(15) P3d(5) 4.S6h(3) S6b(2) 5.S4h(4) +P6d(4) 6.P4f(1) S6c(7) 7.S4g(1) S5d(10) 8.S5f(4) G5b(9) 9.G5h(9) K4a(2) +10.K6i(5) Bx7g+(18) 11.Sx7g(1) S4b 12.P6f(10) P4d(4) 13.K7i(1) K3a(3) +14.P3f(8) P1d(8) 15.P1f(4) P9d(2) 16.P9f(1) P7d 17.N3g(35) N7c(70) 18.B'2f(11) +G5b-4c 19.R4h P3e(39) 20.Bx3e(21) G3d(1) 21.B2f(3) P2d(2) 22.P4e(4) Px4e(32) +23.Sx4e(36) Sx4e(4) 24.Nx4e P'4d 25.B3g(7) R6b(35) 26.P7e(72) N8e(2) 27.Px7d +Nx7g+(6) 28.Nx7g(1) Px4e(4) 29.P7c+ R9b(2) 30.S'8c(37) S'4f(46) 31.Bx4f(10) +Px4f 32.Sx9b+ S'4g(32) 33.Gx4g(12) Px4g+ 34.Rx4g B'5h(2) 35.R'7a(52) K2b(1) +36.R4h(1) G'6g(4) 37.Rx5h(8) Gx5h 38.B'7f R'5i(6) 39.K8h N'5d 40.N'3e(4) +G3d-3c(30) 41.B6g(3) Nx6f(12) 42.S'2c(1) G3cx2c 43.Nx2c+ Gx2c 44.Bx2c+ Kx2c +45.Rx2a+ Resigns +# Time used black: 6.40; white: 7.37 +# +# KAKUGAWARI BOUGIN +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P6d? +# +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f S7c S1e? B*5d! P2d?? P2d S2d P*2g! # +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f S7c S1e? B*5d! B*3h! P4d! P2d P2d S2d P*2g? B2g S2d B5d P5d R2d +# +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f S7c S1e? B*5d! B*3h! P4d! P2d P2d S2d P*2g? B2g B2g R2g +# +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f S7c S1e? B*5d! B*3h! P4d! P2d P2d S2d P*2g? B2g # +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f S7c S1e? B*5d! B*3h! P4d! P4f # +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f S7c S1e? B*5d! B*3h! P4d! +# +P7f P8d P2f G3b G7h P8e B7g P3d S8h B7g+ S7g S4b S3h S7b P2e S3c S2g P7d S2f +# KAKUGAWARI KOSHIKAKE-GIN + +# NAKAHARA's KYUSEN SHOGI + +# HINERI-BISHA + +# 1. 3-4FU GATA +P2f P8d P2e P8e P2d?? P2d R2d P8f P8f P*8g P*2c P8h+ S8h B*3e # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f R8d S3h S4b K4h K4a K3i K3a +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P6d B7g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R3f? P3f R*2g S3h R2h+ R*8f G7a?? P*8b # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R3f? P3f R*2g S3h R2h+ R*8f +R1i R8a+ L*2d P7d L2h+? P7c+ S7c B5e +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R3f? P3f R*2g S3h R2h+ R*8f +R1i R8a+ L*2d P7d P7d P*7c S7c?? B5e +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R3f? P3f R*2g S3h R2h+ R*8f +R1i R8a+ L*2d P7d P7d P*7c G7a +R9a +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R3f? P3f G7b S3h K5b P9e P1d K5h # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R3f? P3f +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P*8g B9g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h P*8f? P*8e # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a P*8e? K3b R8f G7b S6h S4b +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! R8i+? R8f +R9i B8h +R9h R8a+ S7b +R9a P*8g N*8d P8h N7b+ # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! R8i+? B8h G7b R8f P*8c G5i P7d G7h6h P7e S7h +R8h R8h P7f R*6a # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! R8i+? # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! G7b R8f R8f? B8f R*8i R*6a K5b R8a+ +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! G7b R8f G8c? P6f G8d P6e P6e P7d P7d N6e S4b N5c+ S5c R8d R8d B5c+ # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! G7b R8f G8c? P6f G8d P6e P6e P7d P7d N6e S6d R8d R8d B6d # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! G7b R8f G8c? P6f G8d P6e P6e P7d P7d N6e +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e! R8b N7g P6d K4h S6c S3h K4a B9g! G7b R8f P*8d P6f S4b S6h K3b K3i P4d P4f G4c G6g P5d G5f S5c S6g P1d S5h P1e R7f P9d P6e B3a +# 2. 1-4 FU 6-4 FU TYPE HINERI-BISHA +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g S6c B9g R8b P7e S4b R8f P*8d P6f # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g P7d R6f S6c P7e R6f P6f G7b P7d P*7f N8e S7d P*7c G7a P*8b G8b R*7a R*6a R7b+ G7b P7b+ R6c G*7c N7c N7c+ # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g P7d R6f G7b R6d S6c R6f S4b K4h P9d P7e R8b B9g P3d R8f P*8d P7d S7d R7f G7c P*7e S6c P6f # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g P7d R6f +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g +# KUUCHU SENPOU + +# AI YOKOFU +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c? R3d B8h+ S8h B*2e R3b+ S3b S3h S3c B*4e? K6b B2c+ P8f P8f R8f P*8g R7f S7g R2f P*2g B4g+ S4g R2c +# +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c? R3d B8h+ S8h B*2e R3b+ S3b S3h S3c S7g +# +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B8h+ S8h R7f S7g R7d R3f N3c R2f P*2e R8f P*8b P*8c G7b P8b+ S8b P*8c S7a B*8b P*8e R6f S8b P8b+ G8b R6c+ +# NAITO 3-3 KAKU +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B3c R3f R8d R2f S2b P*8g K5b S4h P1d P4f P1e S4g B8h+ S8h N3c P3f P*2e R2h R2d P*2g G7b G3h S6b N3g S2c K6h P7d S7g P6d P9f P9d R2i S6c +# +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B3c R3f R8d R2f S2b P*8g K5b K6h P1d S3h P1e P9f P9d P3f P*8f P8f R8f P3e R8e P7e P*2e R2e R7e B7g P7d S8h N7c P*7f R8e P*8f R5e B5e B5e P4f P*3f R*5f B*6d +# + +# SOME OPENINGS + +# OPENING 11 MISC + +# OPENING 12 FURI-BISHA, HINERI-BISHA + +# OPENING 13 AI-YAGURA + +# OPENING 14 YOKOFU-DORI + +# OPENING 15 AI-GAKARI + +# TUKADA.KIF TSUKADA SPECIAL + +# KAKUGAWARI.KIF KAKU-GAWARI (HABU'S ZUNOO) + +###### MY OPENINGS + +# SOURCE: GUIDE TO SHOGI OPENINGS + +# 5. KIMURA JOUSEKI (NAKAHARA'S SHOGI JOUSEKI) P7f P8d P2f P8e P2e G3b B7g P3d S8h B7g+ S7g S2b G7h S3c S4h S6b P4f P6d S4g S6c P3f P7d K6h K4b G5h G5b P1f P1d P9f P9d S5f S5d P6f P4d K7i K3a K8h K2b N3g N7c P4e P4e P3e S4d P7e P7e P2d P2d R2d P*2c R2h B*6c P1e P1e P*1c L1c N2e L1d P3d P2d N3c+ N3c R2d G2c B*1a K3b P3c+ S3c N*4d S4d R2c+ K2c B4d+ G4c S4e G4d S4d # + +#6.KAKUKAWARI BOUGIN +P7f P8d P2f P8e P2e G3b B7g P3d S8h B7g+ S7g S2b G7h S3c S3h S6b S2g P7d S2f S7c S1e B*5d B*3h P4d P2d P2d S2d S2d R2d G3c R2h P*2g R2g B2g+ B2g R2b P*2h G6b G3i K4b S6f G4c S5e S*5d S6f N3c P5f R2a +# + +#GACCHAN-GIN (SUCCESS) +P7f P8d P2f P8e P2e G3b P2d P2d R2d P*2c R2f P8f P8f R8f G7h R8d P*8g P3d S4h S6b P4f P6d S4g S6c S5f S5d P1f P1d G5h P9d P9f G5b K6h K4b P3f P7d N3g P6e G4h N7c? P3e P3e S4e S4e N4e P4d P*3c N3c S*6d G6b S7c G7c N*3d K5b N2b+ S2b B4d # + +#GACCHAN-GIN (FAILURE) +P7f P8d P2f P8e P2e G3b P2d P2d R2d P*2c R2f P8f P8f R8f G7h R8d P*8g P3d S4h S6b P4f P6d S4g S6c S5f S5d P1f P1d G4h P9d P9f G5b K6h K4b P3f P7d N3g P6e P3e? P3e S4e S4e N4e P7e P*3c N3c N3c+ B3c B3c+ G3c N*4e G3b S*3c G3c N3c+ K3c B*4a K4b B2c+ S*3b P*3c S2c R2c+ P*2b P3b+ S3b +R2cx2b B*5e +# + +#GACCHAN-GIN (YOKOFU) +P7f P8d P2f P8e P2e G3b P2d P2d R2d P*2c R2f P8f P8f R8f G7h R8d P*8g P3d S4h S6b P4f P6d S4g S6c S5f S5d P1f P1d G4h P9d P9f G5b K6h K4b P3f P7d N3g P6e K5h G6b P*2d P2d R2d P*2c R3d B8h+ S8h G3c R3e B*2h N2e G3b P*2b +# +P7f P8d P2f P8e P2e G3b P2d P2d R2d P*2c R2f P8f P8f R8f G7h R8d P*8g P3d S4h S6b P4f P6d S4g S6c S5f S5d P1f P1d G4h P9d P9f G5b K6h K4b P3f P7d N3g P6e K5h G6b P*2d P2d R2d P*2c R3d G5b B2b+ S2b N4e B*4d N5c+ G5c B*5a K5a R3b+ G5b S4e S4e P4e B9i+ S*5c + +# + +# F4dU KISHUU (KISHUU TAIZEN) +P7f P4d? B4d? R4b B5c+ P3d S8h R4g+ S4h?? B8h+ # + +# ONI GOROSHI (GOTE SIPPAI) +P7f P3d N7g P8d N6e S6b? P7e P6d B2b+ S2b B*5e S3c? B6d # ONI GOROSHI (SENTE SASIKIRI) +P7f P3d N7g P8d N6e S6b? P7e P6d B2b+ S2b B*5e B*3c B6d B9i+ P7d R8c P7c+ N7c N5c+ P*5b +# ONI GOROSHI (SENTE FURI) +P7f P3d N7g P8d N6e G6b! P7e P6d B2b+ S2b B*5e G6c! # + +# GOTE NAKABISHA (HAMETE) +P7f P5d P2f R5b P2e P3d P2d? P2d R2d B8h+ S8h B*3c R2h P*2f S7g? R2b S3h B7g+ N7g S*2g +# GOTE F7dU (HAMETE) +P7f P7d B8h5e? P3d B8b+ S8b S8h B*9e R*7g N7c P9f B8d # GOTE F7dU +P7f P7d P2f R7b P2e P3d G7h G3b P2d P2d R2d P7e R3d P7f P*7c N7c B2b+ S2b P*7d N6e B*9e K4a P7c+ B*5a +# KAMA-ITACHI (G4hIN) (GOTE F3dU) +P7f P3d S4h P8d P5f P8e S5g P8f? P8f R8f B2b+ S2b B*7g R8b? P*8d N3c R8h +# +P7f P3d S4h P8d P5f P8e S5g P8f? P8f R8f B2b+ S2b B*7g R8i+ B2b+ B*3c 2b2a B9i+ P4f +# KAMA-ITACHI (GOTE F8dU) +P7f P8d S4h P8e P5f P8f? P8f R8f G7h R7f B6f R8f S8h R8b S5g P5d P5e P5e P*5d +# OPENING MISC. + +# --> KAKU-GAWARI +P7f P8d P2f P8e G7h G3b +# --> YOKOFU-DORI + +# + +# FURI-BISHA, HINERI-BISHA OPENING + +# + +# NAKAHARA'S SHOGI BOOK + +# 1. 3-KEN BISHA +P7f P3d P2f P4d S4h R3b P2e B3c P5f S4b K6h K6b K7h K7b 4i5h P5d P3f 4a5b P4f S5c N3g K8b P4e R4b P2d 2c2d 4e4d 5c4d P*4e S5c B3c+ N3c R2d N4e 3g4e 4b4e R2a+ S7b B*3c P*4g G4g P*4f G5g # + +# 2. 4-KEN BISHA +P7f P3d P2f P4d S4h S3b P5f R4b P2e B3c K6h K6b K7h K7b 4i5h K8b P3f S7b S6h 4a5b 6h5g P5d 6i6h P6d P3e 3d3e S4f P3f S3e P4e B3c+ S3c P2d 2c2d S3ex2d S3cx2d R2d B*3c R2a+ R2b +R2ax2b B2b B*6f B6f P6f R*2h R*4a R2i+ B*4d S*6b +# + +# 3. NAKA BISHA +P7f P3d P2f P4d S4h S4b P5f P5d 4i5h S4c K6h R5b K7h K6b S6h K7b P2e B3c P3f K8b P4f S7b P4e +# NAKAHARA'S KYUSEN SHOGI (1) HINERI-BISHA P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P3d R3f G3c P7f P8f P8f R8f P7e R8b N7g P6d K4h S6c S3h K4a B9g G7b R8f P*8d P6f S4b S6h K3b K3i P4d P4f G4c G6g P5d G5f S5c S6g P1d S5h P1e R7f P9d P6e B3a P4e P4e P6d S5cx6d G6e S6e N6e P*6d B8h G*3c P*4d G3cx4d B4d G4d P*2b P6e P2a+ B5c R2f N*2d P*2e G3e R2h # + +# NAKAHARA'S KYUSEN SHOGI (1) HINERI-BISHA -2 (G6cIN) P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g S6c B9g R8b P7e S4b R8f P*8d P6f # + +# NAKAHARA'S KYUSEN SHOGI (1) HINERI-BISHA -2 (F7dU) P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P9f P1d S3h P6d P7f P8f P8f R8f N7g P7d R6f S6c P7e R6f P6f G7b P7d # ISHIDA-RYUU CHOU-KYUUSEN-1 +P7f P3d P7e P8d R7h P8e K4h S6b P7d P7d? B2b+ S2b B*5e S7c R7d B*6d R7c+ B5e 7c8b B8b R*8c G7b R8e+ +# + +# ISHIDA-RYUU CHOU-KYUUSEN-2 +P7f P3d P7e P8d R7h P8e K4h S6b P7d G7b P7c+ S7c B2b+ S2b B*5e B*3c B7c+ G7c P*7d G8c S*7c R9b +# + +# ISHIDA-RYUU CHOU-KYUUSEN-3 (GOTE SIPPAI) P7f P3d P7e P8d R7h P8e K4h P8f? P8f R8f P7d P7d B2b+ S2b B*9e + +# + +# MASUDA'S ISHIDA-RYUU-1 +P7f P3d P7e P8d R7h P8e K4h S6b K3h P6d K2h S6c S3h P8f P8f R8f B2b S2b R8h P*8g R9h B*8h G7h B7i+ G7i S*8h B*5e S7i B2b+ P8h+ S*7g R8b +B2bx1a +P8hx9h L*8f +# + +# MASUDA'S ISHIDA-RYUU-2 +P7f P3d P7e P8d R7h P8e K4h S6b K3h P6d K2h S6c S3h K4b R7f B8h+ S8h S2b N7g K3b B*9f G7b B8e S3c R8f G4b B6c+ R8f +B6cx7b R8d S*9e +# P7f.P8d.P7e +P7f P8d P7e P8e +# P7f P3d P2f P4d S4h S3b P2e B3c +P7f P3d P2f P4d S4h S3b P2e B3c +# + +# FURIBISHA OPENING +P7f P8d B7g P3d P6f S6b R7h P5d K4h +# +P7f P8d B7g P3d P6f S6b R6h P5d K4h +# +P7f P8d B7g P3d P6f S6b S7h P5d R6h +# +P7f P8d B7g P3d P6f S6b +# +P7f P8d P6f P3d B7g +## + +## HABU'S ZUNO NO.8 LATEST HINERI-BISHA +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S7b P9f? P3d R3f G3c P7f P8f P8f R8f N7g R8b P7e P9d K4h K4b S3h P6d B9g S6c R8f P*8d S6h K3b P6f S4b S6g G7b S5f G4d K3i G5d P4f ## K9gAKU->F9eU +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S7b P9f? P3d R3f G3c P7f P8f P8f R8f N7g R8b P7e P9d K4h K4b S3h P6d B9g P9e P7d R8i+ +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S7b P1f + +# + +# YAGURA JOUSEKI + +# + +# 4. AI YAGURA (NAKAHARA'S SHOGI JOSEKI) P7f P8d S6h P3d S7g S6b P2f S4b S4h G3b G7h P5d P5f K4a K6i G5b P3f P4d G5h S3c B7i B3a P6f P7d +# + +# YAGURA (2) +P7f P8d S6h P3d S7g S6b P5f S4b S4h G3b G7h P5d P2f K4a K6i G5b P3f P4d G5h S3c B7i B3a P6f P7d +# + +# YAGURA (3) +P7f P8d S6h P3d S7g S6b P5f S4b S4h G3b 4i5h P5d K6h K4a K7h G5b P6f P4d B7i S3c G6g 5b4c K8h B3a G7h +# + +# HABU'S YAGURA 1 +P7f P8d S6h P3d S7g S6b S4h?? P7d G7h S7c P6f S6d G5h P8e 5h6g P7e P7e S7e P*7f P8f P8f S8f +# +P7f P8d S6h P3d P6f S6b S4h?? P7d G7h S7c S7g S6d G5h P8e 5h6g P7e P7e S7e P*7f P8f P8f S8f +# +P7f P8d S6h P3d P6f S6b S4h?? P7d G7h S7c S7g S6d G5h P8e P5f P7e P7e S7e P*7f P8f P8f S8f +# + +# HABU'S YAGURA 2 +P7f P8d S6h P3d S7g S6b P5f! P5d S4h S4b 4i5h 6a5b? P6f P4d B7i G4c K6h S3c K7h B3a P3f K4b S3g K3b P3e P3e B3e S5c G6g S6d B6h P5e P6e S6e P5e +# HABU'S YAGURA 3 +P7f P8d S6h P3d S7g S6b P5f P5d S4h S4b 4i5h G3b P6f K4a G6g G5b? B7i S3c P3f P7d P3e P3e B3e S4d B4f P5e R3h # HABU'S YAGURA 4 +P7f P8d S6h P3d S7g S6b P5f P5d S4h S4b 4i5h G3b P6f K4a G6g S6b-5c? P2f P5e P5e B5e P2e S5d P2d P2d R2d P*2c R2h P7d S5g R5b K6h B8b K7h +# HABU'S YAGURA 5 +P7f P8d S6h P3d S7g S6b P5f P5d S4h S4b 4i5h G3b P6f K4a G6g P7d G7h S6b-5c B7i P5e P5e B5e B4f B4f P4f S3c S4g G5b K6i P4d K7i + +# HABU'S YAGURA 6 +P7f P8d S6h P3d S7g S6b P5f P5d S4h S4b 4i5h G3b P6f K4a G6g P7d G7h G5b K6i S6b-5c B7i P6d P2f R6b P2e N7c P3f P6e P6e N6e S6f S6d +## + +# YOKOFU-DORI + +# + +# YOKOFU-DORI (4-5-KAKU) +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B8h+ S8h P*2h S2h B*4e R2d P*2c +# + +# AI YOKOFU-DORI-1 (NAKAHARA'S SHOGI JOSEKI) P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B8h+ S8h R7f S7g R7d R3f N3c R2f P*2e R8f P*8b P*8c G7b P8b+ S8b P*8c S7a B*8b P*8e R6f S8b P8b+ G8b R6c+ +# + +# AI YOKOFU DORI -2 +P7f P3d P2f P8d P2e P8e G7h G3b P2d 2c2d R2d P8f 8g8f R8f R3d B8h+ S8h R7f S7g R7d 3d7d 7c7d P*8b S8b B*5e R*8e R*8f R8f S8f P*2h +# + +# K3cAKU SENPOU - 1 +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B3c R3f R8d R2f S2b P*8g K5b B3c+? N3c B*2a G3a P*2c P*2e P2b+ G2a R3f G2b +# K3cAKU SENPOU - 2 (SENTE G4hIN --> GOTE YAYA GOOD) P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B3c R3f R8d R2f S2b P*8g K5b S4h P1d P4f P1e S4g B8h+ S8h N3c P3f P*2e R2h R2d P*2g G7b G3h S6b N3g S2c K6h P7d S7g P6d P9f P9d R2i S6c +# K3cAKU SENPOU - 3 (SENTE G3hIN->SENTE FURI) P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B3c R3f R8d R2f S2b P*8g K5b S3h B8h+ S8h B*3e R3f P*3d K6h P*2h # K3cAKU SENPOU - 4 (SENTE G6hYOKU->GOTE YAYA GOOD) P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P8f P8f R8f R3d B3c R3f R8d R2f S2b P*8g K5b K6h P1d S3h P1e P9f P9d P3f P*8f P8f R8f P3e R8e P7e P*2e R2e R7e B7g P7d S8h N7c P*7f R8e P*8f R5e B5e B5e P4f P*3f R*5f B*6d +## + +# YOKOFU-DORI (F2cU) YOKOFUDORI GUIDE +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R3d B8h+ S8h B*4e? R3e B2g+ B*1e K4a P3f P8f G3h 2g3h S3h G*2d B2d P2d K5h + +# YOKOFU-DORI P2c-2 +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R3d B8h+ S8h B*2e R3b+ S3b S3h S3c +# YOKOFU-DORI F2cU-3 +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R3d B8h+ S8h B*2e R3f B3f P3f R*2g S3h R2e+ S7g +# YOKOFU-DORI F2cU-4 +P7f P3d P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R3d B8h+ S8h B*2e R3f B3f P3f P8f P8f R8f K6h R8b S3h S2b P4f S7b P3e K4b B*4g P6d N3g +# + +# AI GAKARI + +# AIGAKARI HAMETE +P2f P8d P2e P8e P2d?? P2d R2d P8f P8f P*8g! P*2c 8g8h+ S8h B*3e R2h 3e5g+ 2c2b+ R2b P*2c R1b B*2b P*2d 2b1a+ R1a L*2g B*4e L2d P*2g +# + +# (AIGAKARI: TSUKADA SPECIAL) + +# TUKADA-1 (GOTE H8bISHA -> SENTE LITTLE SUCCESS) + +#P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f + +#S6b P1f P1d S3h + +#P6d P7f P8f P8f R8f P*2d P2d R2d R8b + +#P1e P1e P*1d + +#P*2c R6d R8h+ R6b+ G6b G8h P3d R*8c B*7b + +#R8g+ P7d P*8c N7c + +# TUKADA-2 (GOTE G6cIN -> SENTE SUCCESS) + +#P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f + +#S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d + +#S6c? P1e P*2c R2e P1e P*1d R8b R1e P3d P*8g + +# TUKADA-3 (GOTE H8bISHA -> SENTE FURI) + +#P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f + +#S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d + +#R8b R6d? R8h+ R6b+ G6b S8h P*2g + +# TSUKADA SPECIAL MONOGATARI + +## TSUKADA SPECIAL +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S7b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S7b P1f P1d P9f P9d S3h P6d P7f P8f P8f R8f P*2d P2d R2d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f K4a? P1e # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P3d P7f P8f P8f R8f P*2d P2d R2d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f S6c? B7g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P3d R3f G3c B7g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P3d R3f B8h+ S8h B*2h R3d N3c L1g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d P*2c? R6d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d S6c? P1e P*2c R2e P1e P*1d R8b R1e P3d P*8g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d R8b! R6d R8h+ R6b+ G6b S8h # +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d R8b! P1e P*8f P*8d P8g+ G8g R8d P*8f P1e P*1d P*2c R2e L1d +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d R8b! P1e P1e P*1d P*8f P*2c P8g+ G8g +# +P2f P8d P2e P8e G7h G3b P2d P2d R2d P*2c R2f S6b P1f P1d S3h P6d P7f P8f P8f R8f P*2d P2d R2d R8b! P1e P1e P*1d P*2c R6d R8h+ R6b+ G6b S8h +# + diff --git a/src/.LVS_ENV b/src/.LVS_ENV new file mode 100644 index 0000000..a7c1e05 --- /dev/null +++ b/src/.LVS_ENV @@ -0,0 +1 @@ +/mount/capella.u/mutz/verena/examples/multpipe/vhdl/mylib \ No newline at end of file diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..3a9359f --- /dev/null +++ b/src/Makefile @@ -0,0 +1,456 @@ +# Makefile for GNU Shogi +# Copyright (c) 1993, 1994 Matthias Mutz +# +# GNU Shogi is based on GNU Chess +# Copyright (c) 1992 Free Software Foundation +# +# This file is part of GNU SHOGI. +# +# GNU Shogi 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 1, or (at your option) +# any later version. +# +# GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# gnushogi is a curses-based shogi. +# gnushogix is the xshogi based shogi. +# gnushogir is a plain dumb-terminal shogi (but with full variation output). +# pat2inc converts pattern textfile to include file +# sizetest shows memory usage of main data structures +# + +# change this if you need shorter filenames +GNUSHOGI= gnushogi +GNUSHOGIR= gnushogir +GNUSHOGIX= gnushogix + +# The version number of this GNU Shogi and XShogi release +VERS= 1.2p03 + +# Relevant file areas. +DIST= ../README-$(VERS) ../doc ../misc ../src + +# Installation directory +prefix=/usr/local +#prefix=/public/projects/shogi + +# Change these to something less transitory, like /usr/games, and then +# compile. Ask your system admin / unix guru to put gnushogi.{hsh,lng,tbk} +# in $(LIBDIR). +# Where the binaries live. +BINDIR= $(prefix)/games +#BINDIR=/public/projects/shogi/bin + +# Where language description, our book, and the persistent hash live. +LIBDIR= $(prefix)/games/lib/gnushogi +#LIBDIR=/public/projects/shogi/lib + +# Distribution directory +DISTDIR=/public/projects/shogi + +# Programs being distributed +PROGS=gnushogi-$(VERS) + +# For _pow external +LIBS= -lm +# For _pow and _conio_kbhit external +#LIBS= -lm -lpc + +# Display routines. +LCURSES=-lcurses -ltermcap + +# The compiler used for compiling this software. +# Use this for a plain C compiler +#CC= cc $(OPT) $(GENOPT) +# Use this for DEC's ANSI C compiler on Ultrix +#CC= c89 $(OPT) $(GENOPT) +# Use this if you are lucky enough to have GNU CC. +#CC= /usr/pub/bin/gcc -fsigned-char $(OPT) $(GENOPT) +CC= gcc -W -fsigned-char $(OPT) $(GENOPT) +#CC= cc $(OPT) $(GENOPT) + +# Miscellaneous CFLAGS. Uncomment the one you need and comment the other +#CFLAGS= -p -Dinline="" -traditional-cpp +#CFLAGS= -O4 -Qpath . # SunOS cc using unprotoize +#CFLAGS= -O4 # Sun acc +#CFLAGS= -g -traditional-cpp # debug +#CFLAGS= -O2 # DEC ANSI C (c89) on Ultrix. +#CFLAGS= +O3 -Aa -D_HPUX_SOURCE -DSYSV # HPUX cc +#CFLAGS= -O -finline-functions -fstrength-reduce -D__mips -D__LANGUAGE_C # gnu cc 1.40 on DS5000 +#CFLAGS= -O -finline-functions -fstrength-reduce # gnu cc 1.40 on others +#CFLAGS= -g -w -finline-functions -fstrength-reduce # gnu cc 1.40 on others +#CFLAGS= -O2 -funroll-loops -D__mips -D__LANGUAGE_C # gnu cc 2.00 on DS5000 +#CFLAGS= -O2 -D__alpha -D__LANGUAGE_C # gnu cc 2.00 on Flamingo +#CFLAGS= -g -finline-functions -fstrength-reduce -DOLDTIME -DNOFIONREAD # gnu cc 1.40 on sun4 +#CFLAGS= -O2 -funroll-loops -traditional-cpp -I/usr/local/include/ansi # gnu cc 2.00 on apollo (capella) +#CFLAGS= -O2 -funroll-loops -traditional-cpp -DNO_STRING_INCLUDE -DNOFIONREAD # gnu cc 2.00 (hawk) +#CFLAGS= -O2 -funroll-loops -DSEVENBIT # djgpp +#CFLAGS= -g -funroll-loops # gnu cc 2.00 on SunOS with debug +CFLAGS= -O2 -funroll-loops # gnu cc 2.00 on SunOS + +# flags for DJGPP package +#COFF2EXE= coff2exe $(GNUSHOGI) +#COFF2EXER= coff2exe $(GNUSHOGIR) + +# Compression program for building distribution files +COMPRESS= gzip +Z= gz +#COMPRESS= compress +#Z= Z + +# lines per uuencoded file +UULINES=1500 + +# compile options for gnushogi +# -DQUIETBACKGROUND don't print post information in background ( easy OFF) +# -DNOLIST don't list game after exit +# -DNOBYTEOPS if your machine does not support bzero and bcopy +# -DNOMEMOPS if your machine does not support memset and memcpy +# -DNODYNALPHA don't dynamically adjust alpha +# -DHISTORY use history killer hueristic +# -DHASGETTIMEOFDAY use gettimeofday for more accurate timing +# -DLONG64 if you have 64bit longs +# -DSYSV if you are using SYSV +# -DCACHE Cache static evaluations +# -DQUIETBOOKGEN Don't print errors while loading a book or generating a binbook +# -DSEMIQUIETBOOKGEN Print less verbose errors while reading book or generating binbook +# -DNULLMOVE include null move heuristic +# -DXSHOGI create xshogi version +# -DBAREBONES do not print statistics (for gnushogix version) +# -DHARDTIMELIMIT reaching the time control means loosing the game +# some debug options +# -DDEBUG8 dump board,movelist,input move to /tmp/DEBUG if illegal move +# -DDEBUG9 dump move list from test command +# -DDEBUG10 dump board and move after search before !easy begins +# -DDEBUG11 dump board when the move is output +# -DDEBUG12 dump boards between moves +# -DDEBUG13 dump search control information for each move to /tmp/DEBUG +# -DDEBUG40 include extra values of variables for debugging in game list +# -DDEBUG41 dump post output to /tmp/DEBUG +# -DDEBUG_EVAL dump evaluation of position to /tmp/EVAL on input command "eval" +# the rest of the debug options are tied to the debuglevel command +# -DDEBUG -DDEBUG4 set up code for debuglevel command +# debuglevel +# 1 always force evaluation in evaluate +# 4 print move list after search +# 8 print move list after book before search +# 16 print move list after each ply of search +# 32 print adds to transposition table +# 64 print returns from transposition table lookups +# 256 print search tree as it is generated +# 512 debug trace +# 1024 interactive tree print +# debug? p# where # is no. of plys to print from top of tree (default all plys) +# XXXX moves specifying branch of tree to print (default all branches) +# return terminates input +# 2048 non-interactive trace print + +# normal +OPT= -DVERYBUGGY -DQUIETBACKGROUND -DHARDTIMELIMIT -DHASGETTIMEOFDAY -DCACHE -DNULLMOVE -DHISTORY -DEXACTHISTORY # -DSEMIQUIETBOOKGEN +# small memory +#OPT= -DEASY_OPENINGS -DSMALL_MEMORY -DSLOW_CPU -DSAVE_PTYPE_DISTDATA -DSAVE_NEXTPOS -DVERYBUGGY -DQUIETBACKGROUND -DHARDTIMELIMIT -DHASGETTIMEOFDAY -DNULLMOVE -DCACHE -DHISTORY # -DSAVE_SSCORE -DEXACTHISTORY -DSEMIQUIETBOOKGEN +#OPT= -DSMALL_MEMORY -DVERY_SLOW_CPU -DSAVE_PTYPE_DISTDATA -DSAVE_NEXTPOS -DVERYBUGGY -DQUIETBACKGROUND -DHARDTIMELIMIT -DHASGETTIMEOFDAY -DNULLMOVE -DCACHE -DHISTORY # -DSAVE_SSCORE -DEXACTHISTORY -DSEMIQUIETBOOKGEN + +# options for genmove.c in order to support move ordering at cost of speed +# -DTESUJIBONUS add bonus to a move that semms to be a tesuji +# -DFIELDBONUS add bonus to regular moves +# -DDROPBONUS add bonus to drops +# -DDEEPSEARCHCUT check for moves not to consider at deep plys +# slow CPU +#GENOPT= -DCHECKBONUS -DDEEPSEARCHCUT -DTESUJIBONUS +# fast CPU +GENOPT= -DCHECKBONUS -DDEEPSEARCHCUT -DTESUJIBONUS -DDROPBONUS -DFIELDBONUS + +# Special options for gnushogix +XSHOGI= -DXSHOGI -DBAREBONES -DHARDTIMELIMIT + +# Debug options for Dgnushogir +DEBUG= -DNONDSP -DDEBUG_EVAL -DDEBUG -DDEBUG4 -DHASHKEYTEST -DHASHTEST -DCACHETEST -DDEBUG41 -DDEBUG9 -DDEBUG10 # -DBOOKTEST + +# The hashfile is a record of positions seen. It is used by +# GNU Shogi to avoid making the same mistakes, a form of learning. +HASH= -DHASHFILE=\"$(LIBDIR)/gnushogi.hsh\" + +# The "book" is a record of the first few moves, for playing good +# moves easily and quickly, saving time, and irritating the human +# opponent. +TEXTBOOK= -DBOOK=\"$(LIBDIR)/gnushogi.tbk\" +BINBOOK = -DBINBOOK=\"$(LIBDIR)/gnushogi.bbk\" + +# The language file describes capabilities of the program. Perhaps +# it is useful for non-English speaking countries and customizing +# for their convenience and shogi happiness. +LANG= -DLANGFILE=\"../misc/gnushogi.lng\" + +# The pattern file contains various opening patterns. The program tries to +# obtain such a pattern in the opening stage. Sequences of opening +# patterns may be described in order to support the correct order of moves. +PATTERN= -DPATTERNFILE=\"../misc/gnushogi.pat\" + +all : $(GNUSHOGI) $(GNUSHOGIX) gnushogi.bbk # sizetest pat2inc + +$(GNUSHOGI): mainN.o globals.o bookN.o genmoveN.o patternN.o ataksN.o utilN.o evalN.o initN.o searchN.o tcontrlN.o dspcomN.o uxdsp.o + $(CC) $(CFLAGS) -o $(GNUSHOGI) mainN.o globals.o bookN.o genmoveN.o patternN.o ataksN.o utilN.o evalN.o initN.o searchN.o tcontrlN.o dspcomN.o uxdsp.o $(LCURSES) $(LIBS) + $(COFF2EXE) + +$(GNUSHOGIX): mainX.o globals.o bookX.o genmoveX.o patternX.o ataksN.o utilX.o evalX.o initX.o searchX.o tcontrlX.o dspcomX.o nondspX.o + $(CC) $(CFLAGS) -o $(GNUSHOGIX) mainX.o globals.o bookX.o genmoveX.o patternX.o ataksN.o utilX.o evalX.o initX.o searchX.o tcontrlX.o dspcomX.o nondspX.o $(LIBS) + +$(GNUSHOGIR): mainN.o globals.o bookN.o genmoveR.o patternR.o ataksR.o utilR.o evalR.o initR.o searchR.o tcontrlN.o dspcomR.o nondspR.o + $(CC) $(CFLAGS) -o $(GNUSHOGIR) mainN.o globals.o bookN.o genmoveR.o patternR.o ataksR.o utilR.o evalR.o initR.o searchR.o tcontrlN.o dspcomR.o nondspR.o $(LIBS) + $(COFF2EXER) + +D$(GNUSHOGIR): mainDR.o globals.o bookDR.o genmoveDR.o patternDR.o ataksDR.o utilDR.o evalDR.o initDR.o searchDR.o tcontrlDR.o dspcomDR.o nondspDR.o + $(CC) $(DEBUG) $(CFLAGS) -o D$(GNUSHOGIR) mainDR.o globals.o bookDR.o genmoveDR.o patternDR.o ataksDR.o utilDR.o evalDR.o initDR.o searchDR.o tcontrlDR.o dspcomDR.o nondspDR.o $(LIBS) $(LIBS) + +pat2inc: nondspDR.o dspcomDR.o globals.o bookDR.o genmoveDR.o patternP.o ataksDR.o utilDR.o evalDR.o initDR.o searchDR.o tcontrlDR.o pat2inc.o + $(CC) $(CFLAGS) -o pat2inc patternP.o globals.o bookDR.o genmoveDR.o ataksDR.o utilDR.o evalDR.o searchDR.o tcontrlDR.o initDR.o nondspDR.o dspcomDR.o pat2inc.o $(LIBS) + +sizetest: sizetest.o + $(CC) $(CFLAGS) -o sizetest sizetest.o $(LIBS) + +pat2inc.o: pat2inc.c pattern.h gnushogi.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) $(LANG) $(BINBOOK) $(PATTERN) -c pat2inc.c + +sizetest.o: sizetest.c gnushogi.h eval.h + $(CC) $(CFLAGS) $(HASH) -c sizetest.c + +globals.o: globals.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c globals.c + +mainN.o: main.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) $(BINBOOK) -c main.c + mv main.o mainN.o + +mainX.o: main.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) $(BINBOOK) $(XSHOGI) -c main.c + mv main.o mainX.o + +mainDR.o: main.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(BINBOOK) $(HASH) -c main.c + mv main.o mainDR.o + +genmoveN.o: genmove.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c genmove.c + mv genmove.o genmoveN.o + +genmoveR.o: genmove.c gnushogi.h version.h + $(CC) -DNONDSP -DDEBUG_EVAL $(CFLAGS) $(HASH) -c genmove.c + mv genmove.o genmoveR.o + +genmoveDR.o: genmove.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -c genmove.c + mv genmove.o genmoveDR.o + +genmoveX.o: genmove.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) $(XSHOGI) \ + -c genmove.c + mv genmove.o genmoveX.o + +bookN.o: book.c gnushogi.h version.h + $(CC) -DNONDSP $(CFLAGS) $(HASH) $(TEXTBOOK) $(BINBOOK) -c book.c + mv book.o bookN.o + +bookX.o: book.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) $(TEXTBOOK) $(BINBOOK) $(XSHOGI) \ + -c book.c + mv book.o bookX.o + +bookDR.o: book.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) $(TEXTBOOK) $(BINBOOK) \ + -c book.c + mv book.o bookDR.o + +patternN.o: pattern.c gnushogi.h pattern.h pattern.inc + $(CC) $(CFLAGS) -c pattern.c + mv pattern.o patternN.o + +patternX.o: pattern.c gnushogi.h pattern.h pattern.inc + $(CC) $(CFLAGS) $(XSHOGI) -c pattern.c + mv pattern.o patternX.o + +patternR.o: pattern.c gnushogi.h pattern.h pattern.inc + $(CC) $(CFLAGS) -DNONDSP -c pattern.c + mv pattern.o patternR.o + +patternDR.o: pattern.c gnushogi.h pattern.h pattern.inc + $(CC) $(CFLAGS) $(DEBUG) -c pattern.c + mv pattern.o patternDR.o + +# to create "pattern.inc" with "pat2inc", the external +# pattern textfile must be used. + +patternP.o: pattern.c gnushogi.h pattern.h + $(CC) $(DEBUG) $(CFLAGS) -DEXTPATTERNFILE $(PATTERN) -c pattern.c + mv pattern.o patternP.o + +ataksN.o: ataks.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c ataks.c + mv ataks.o ataksN.o + +ataksR.o: ataks.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -DDEBUG_EVAL -DNONDSP -c ataks.c + mv ataks.o ataksR.o + +ataksDR.o: ataks.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -c ataks.c + mv ataks.o ataksDR.o + +utilN.o: util.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c util.c + mv util.o utilN.o + +utilX.o: util.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) $(XSHOGI) -c util.c + mv util.o utilX.o + +utilR.o: util.c gnushogi.h version.h + $(CC) -DNONDSP -DDEBUG_EVAL $(CFLAGS) $(HASH) $(XSHOGI) -c util.c + mv util.o utilR.o + +utilDR.o: util.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -c util.c + mv util.o utilDR.o + +evalN.o: eval.c eval.h gnushogi.h version.h pattern.h + $(CC) $(CFLAGS) $(HASH) -c eval.c + mv eval.o evalN.o + +evalX.o: eval.c eval.h gnushogi.h version.h pattern.h + $(CC) $(XSHOGI) $(CFLAGS) $(HASH) -c eval.c + mv eval.o evalX.o + +evalR.o: eval.c eval.h gnushogi.h version.h pattern.h + $(CC) -DDEBUG_EVAL $(CFLAGS) $(HASH) -c eval.c + mv eval.o evalR.o + +evalDR.o: eval.c eval.h gnushogi.h version.h pattern.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -c eval.c + mv eval.o evalDR.o + +initN.o: init.c gnushogi.h version.h pattern.h + $(CC) $(CFLAGS) $(HASH) $(LANG) -c init.c + mv init.o initN.o + +initX.o: init.c gnushogi.h version.h pattern.h + $(CC) $(CFLAGS) $(HASH) $(LANG) $(XSHOGI) -c init.c + mv init.o initX.o + +initR.o: init.c gnushogi.h version.h pattern.h + $(CC) $(CFLAGS) $(HASH) $(LANG) -DNONDSP -c init.c + mv init.o initR.o + +initDR.o: init.c gnushogi.h version.h pattern.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) $(LANG) -c init.c + mv init.o initDR.o + +searchN.o: search.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c search.c + mv search.o searchN.o + +searchX.o: search.c gnushogi.h version.h + $(CC) $(XSHOGI) $(CFLAGS) $(HASH) \ + -c search.c + mv search.o searchX.o + +searchR.o: search.c gnushogi.h version.h + $(CC) -DNONDSP -DDEBUG_EVAL $(CFLAGS) $(HASH) -c search.c + mv search.o searchR.o + +searchDR.o: search.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -c search.c + mv search.o searchDR.o + +tcontrlN.o: tcontrl.c gnushogi.h version.h + $(CC) $(CFLAGS) -c tcontrl.c + mv tcontrl.o tcontrlN.o + +tcontrlX.o: tcontrl.c gnushogi.h version.h + $(CC) $(XSHOGI) $(CFLAGS) -c tcontrl.c + mv tcontrl.o tcontrlX.o + +tcontrlDR.o: tcontrl.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) -c tcontrl.c + mv tcontrl.o tcontrlDR.o + +uxdsp.o: uxdsp.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c uxdsp.c + +nondspX.o: nondsp.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -DNONDSP $(XSHOGI) \ + -c nondsp.c + mv nondsp.o nondspX.o + +nondspR.o: nondsp.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -DNONDSP \ + -c nondsp.c + mv nondsp.o nondspR.o + +nondspDR.o: nondsp.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -DNONDSP \ + -c nondsp.c + mv nondsp.o nondspDR.o + +dspcomN.o: dspcom.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -c dspcom.c + mv dspcom.o dspcomN.o + +dspcomX.o: dspcom.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -DNONDSP $(XSHOGI) \ + -c dspcom.c + mv dspcom.o dspcomX.o + +dspcomR.o: dspcom.c gnushogi.h version.h + $(CC) $(CFLAGS) $(HASH) -DDEBUG_EVAL -DNONDSP -DNOFIONREAD \ + -c dspcom.c + mv dspcom.o dspcomR.o + +dspcomDR.o: dspcom.c gnushogi.h version.h + $(CC) $(DEBUG) $(CFLAGS) $(HASH) -DNONDSP -DNOFIONREAD \ + -c dspcom.c + mv dspcom.o dspcomDR.o + +gnushogi.bbk: $(GNUSHOGIR) + -rm ./gnushogi.bbk + echo quit >test + cat ../misc/gnushogi.tbk > _tmp_t + cat test| ./$(GNUSHOGIR) -b _tmp_t -B ./gnushogi.bbk -S 8000 -P 40 3 0 + rm test _tmp_t + + +distribution: + -patchlevel=`cat $(DISTDIR)/gnushogi-$(VERS)/src/version.h|grep patchlevel|sed -e 's/[^0-9]//g'` ;\ + echo "GNU patchlevel is $$patchlevel" ;\ + cd $(DISTDIR) ;\ + rm -f gnushogi.tar.$(VERS).$(Z)* ;\ + tar cf - $(PROGS) | $(COMPRESS) > $(DISTDIR)/gnushogi-$(VERS).tar.$(Z) ;\ +# rm -f gnushogi.tar.$(VERS).$(Z).uu* ;\ +# uuencode gnushogi-$(VERS).tar.$(Z) gnushogi-$(VERS).tar.$(Z) > gnushogi-$(VERS).tar.$(Z).uu ;\ +# rm -f x?? ;\ +# split -$(UULINES) gnushogi-$(VERS).tar.$(Z).uu ;\ +# for i in x??; do \ +# mv $$i $(DISTDIR)/GNU_Shogi_$$i; \ +# done + +install: + -cp gnushogi $(BINDIR)/gnushogi + -cp gnushogix $(BINDIR)/gnushogix + -cp gnushogir $(BINDIR)/gnushogir + -cp ./gnushogi.bbk $(LIBDIR)/gnushogi.bbk + +clean: + -rm -f gnushogix gnushogi gnushogir Dgnushogir sizetest pat2inc + -echo $(DISTDIR)/gnushogi-$(VERS) + -rm -f $(DISTDIR)/gnushogi-$(VERS)/src/gnushogi.bbk + -find $(DISTDIR)/gnushogi-$(VERS) \( -name '*.o' -o -name '*~' -o -name 'CL*' -o -name 'PATCH*' -o -name '#*#' -o -name '%*%' -o -name '*orig' -o -name 'CL*' -o -name '*prt' -o -name '*bak' -o -name '*BAK' \) -exec rm -f {} \; + diff --git a/src/ataks.c b/src/ataks.c new file mode 100644 index 0000000..0f87dac --- /dev/null +++ b/src/ataks.c @@ -0,0 +1,342 @@ +/* + * ataks.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "gnushogi.h" + +#ifdef DEBUG +#include +#endif + + +#if defined DEBUG + +void +ataks (short int side, long int *a) +/* + * Fill array atak[][] with info about ataks to a square. Bits 16-31 are set + * if the piece (king..pawn) ataks the square. Bits 0-15 contain a count of + * total ataks to the square. + */ + +{ + register short u, sq; + long int c; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char *ppos, *pdir; +#endif + short i, piece; + small_short *PL; + + array_zero (a, NO_SQUARES * sizeof (a[0])); + + PL = PieceList[side]; + for (i = PieceCnt[side]; i >= 0; i--) + { short ptyp; + sq = PL[i]; + piece = board[sq]; + ptyp = ptype[side][piece]; + c = control[piece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + do { + a[u] = ((a[u]+1) | c); +#ifdef SAVE_NEXTPOS + u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u) + : next_direction(ptyp,&d,sq)); +#else + u = ((color[u] == neutral) ? ppos[u] : pdir[u]); +#endif + } while (u != sq); + } +} + +#endif + + +#if defined DEBUG || defined DEBUG_EVAL + +void +debug_ataks (FILE *D, long *atk) +{ + short l,c,i; + fprintf(D, "\n"); + for (l = NO_ROWS-1; l >= 0; l--) { + for (c = 0; c < NO_COLS; c++) { + short sq = (l * NO_COLS) + c; + long v = atk[sq]; + short n = (short)(v & CNT_MASK); + char s[20]; + fprintf(D,"%2d",n); + strcpy(s,""); + if ( v & ctlP ) strcat(s,"P"); + if ( v & ctlPp ) strcat(s,"+P"); + if ( v & ctlL ) strcat(s,"L"); + if ( v & ctlLp ) strcat(s,"+L"); + if ( v & ctlN ) strcat(s,"N"); + if ( v & ctlNp ) strcat(s,"+N"); + if ( v & ctlS ) strcat(s,"S"); + if ( v & ctlSp ) strcat(s,"+S"); + if ( v & ctlG ) strcat(s,"G"); + if ( v & ctlB ) strcat(s,"B"); + if ( v & ctlBp ) strcat(s,"+B"); + if ( v & ctlR ) strcat(s,"R"); + if ( v & ctlRp ) strcat(s,"+R"); + if ( v & ctlK ) strcat(s,"K"); + fprintf(D,s); + for (i = strlen(s); i < 5; i++) + fprintf(D," "); + fprintf(D," "); + } + fprintf(D,"\n"); + } + fprintf(D, "\n"); +} + +#endif + + +#define CHECK_DISTANCE + + +int +SqAtakd (short int square, short int side, short int *blockable) + +/* + * See if any piece with color 'side' ataks sq. + * *blockable == attack could be blocked by drop + */ + +{ +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char *ppos, *pdir; +#endif + register short u, ptyp; + + if ( MatchSignature(threats_signature[side]) ) { +#ifdef DEBUG + short i,n, sq; + long int a[NO_SQUARES]; + ataks(side,a); + for ( i = 0, n = -1; i < NO_SQUARES; i++ ) + if (a[i] != atak[side][i]) { + n = i; printf("atak #check error on square %d\n",i); + } + if ( n >= 0 ) { + debug_ataks (stdout, a); + debug_ataks (stdout, atak[side]); + debug_position (stdout); + printf("%d pieces\n",PieceCnt[side]); + for ( i = PieceCnt[side]; i>= 0; i-- ) { + short sq, piece; + sq = PieceList[side][i]; + piece = board[sq]; + printf("square %d is %d with piece %d\n", i, sq, piece); + } + printf("hashkey = %ld hashbd = %ld\n",hashkey,hashbd); + assert(a[n] == atak[side][n]); + } +#endif +#ifdef notdef + printf("atak array for %s available for SqAtakd!\n",ColorStr[side]); +#endif + *blockable = true; /* don't know */ + return(Anyatak(side,square)); + } + + /* + * First check neigboured squares, + * then check Knights. + * then check Bishops, + * last check Rooks, + */ + + *blockable = false; + + /* try a capture from direct neighboured squares */ + + ptyp = ptype[black][king]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + pdir = (*nextdir[ptyp])[square]; + u = pdir[square]; +#endif + do + { + if (color[u] == side) + /* can piece reach square in one step ? */ +#ifdef CHECK_DISTANCE + if ( piece_distance(side,board[u],u,square) == 1 ) + return(true); +#else + { + short v; + short ptypv = ptype[side][board[u]]; +#ifdef SAVE_NEXTPOS + short dv; + v = first_direction(ptypv,&dv,u); +#else + unsigned char *qdir; + qdir = (*nextdir[ptypv])[u]; + v = qdir[u]; +#endif + do + { + if (v == square) + return (true); +#ifdef SAVE_NEXTPOS + v = next_direction(ptypv,&dv,u); +#else + v = qdir[v]; +#endif + } while (v != u); + } +#endif +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,square); +#else + u = pdir[u]; +#endif + } while (u != square); + + /* try a knight capture (using xside's knight moves) */ + + ptyp = ptype[side ^ 1][knight]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + pdir = (*nextdir[ptyp])[square]; + u = pdir[square]; +#endif + do + { + if (color[u] == side && board[u] == knight) + return (true); +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,square); +#else + u = pdir[u]; +#endif + } while (u != square); + + *blockable = true; + + /* try a (promoted) bishop capture */ + + ptyp = ptype[black][bishop]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + ppos = (*nextpos[ptyp])[square]; + pdir = (*nextdir[ptyp])[square]; + u = ppos[square]; +#endif + do + { + if (color[u] == neutral) +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,square,u); +#else + u = ppos[u]; +#endif + else + { + if (color[u] == side && (unpromoted[board[u]] == bishop)) + return (true); +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,square); +#else + u = pdir[u]; +#endif + } + } while (u != square); + + /* try a (promoted) rook capture */ + + ptyp = ptype[black][rook]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + ppos = (*nextpos[ptyp])[square]; + pdir = (*nextdir[ptyp])[square]; + u = ppos[square]; +#endif + do + { + if (color[u] == neutral) +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,square,u); +#else + u = ppos[u]; +#endif + else + { + if (color[u] == side && (unpromoted[board[u]] == rook)) + return (true); +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,square); +#else + u = pdir[u]; +#endif + } + } while (u != square); + + /* try a lance capture (using xside's lance moves) */ + + ptyp = ptype[side ^ 1][lance]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + ppos = (*nextpos[ptyp])[square]; + u = ppos[square]; +#endif + do + { + if (color[u] == neutral) +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,square,u); +#else + u = ppos[u]; +#endif + else + { + if (color[u] == side && (board[u] == lance)) + return (true); + u = square; + } + } while (u != square); + + return (false); + +} diff --git a/src/book.c b/src/book.c new file mode 100644 index 0000000..c0c2686 --- /dev/null +++ b/src/book.c @@ -0,0 +1,931 @@ +/* + * book.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software + * Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) any later + * version. + * + * GNU Shogi 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 + * GNU Shogi; see the file COPYING. If not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" +#ifdef MSDOS +#include +#endif +#if !defined MSDOS && !defined THINK_C +#define O_BINARY 0 +#endif +#include +#ifdef THINK_C +#include +/* #define BOOKTEST */ +#endif + + +#include "book.h" + + + +unsigned booksize = BOOKSIZE; +unsigned short bookmaxply = BOOKMAXPLY; +unsigned bookcount = 0; + +#ifdef BOOK +char *bookfile = BOOK; +#else +char *bookfile = NULL; +#endif +#ifdef BINBOOK +char *binbookfile = BINBOOK; +#else +char *binbookfile = NULL; +#endif + + + +static char bmvstr[3][7]; + +static ULONG bhashbd; +static ULONG bhashkey; + + +void +Balgbr (short int f, short int t, short int flag) + + + /* + * Generate move strings in different formats. + */ + +{ + short promoted = false; + + if ( (f & 0x80) != 0) + { + f &= 0x7f; + promoted = true; + } + + if ( f > NO_SQUARES ) + { short piece; + piece = f - NO_SQUARES; + if ( f > (NO_SQUARES+NO_PIECES) ) + piece -= NO_PIECES; + flag = (dropmask | piece); + } + if ( (t & 0x80) != 0 ) + { + flag |= promote; + t &= 0x7f; + } + if ( f == t && (f != 0 || t != 0) ) + { +#if !defined XSHOGI + char buffer[80]; + sprintf(buffer,"error in algbr: FROM=TO=%d, flag=0x%4x\n",t,flag); + ShowMessage(buffer); +#endif + bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = '\0'; + } + else + if ( (flag & dropmask) != 0 ) + { + /* bmvstr[0]: P*3c bmvstr[1]: P'3c */ + short piece = flag & pmask; + bmvstr[0][0] = pxx[piece]; + bmvstr[0][1] = '*'; + bmvstr[0][2] = cxx[column (t)]; + bmvstr[0][3] = rxx[row (t)]; + bmvstr[0][4] = bmvstr[2][0] = '\0'; + strcpy (bmvstr[1], bmvstr[0]); + bmvstr[1][1] = '\''; + } + else + if (f != 0 || t != 0) + { + /* algebraic notation */ + /* bmvstr[0]: 7g7f bmvstr[1]: (+)P7g7f(+) bmvstr[2]: (+)P7f(+) */ + bmvstr[0][0] = cxx[column (f)]; + bmvstr[0][1] = rxx[row (f)]; + bmvstr[0][2] = cxx[column (t)]; + bmvstr[0][3] = rxx[row (t)]; + bmvstr[0][4] = '\0'; + if (promoted) + { + bmvstr[1][0] = bmvstr[2][0] = '+'; + bmvstr[1][1] = bmvstr[2][1] = pxx[board[f]]; + strcpy(&bmvstr[1][2],&bmvstr[0][0]); + strcpy(&bmvstr[2][2],&bmvstr[0][2]); + } + else + { + bmvstr[1][0] = bmvstr[2][0] = pxx[board[f]]; + strcpy(&bmvstr[1][1],&bmvstr[0][0]); + strcpy(&bmvstr[2][1],&bmvstr[0][2]); + } + if (flag & promote) + { + strcat(bmvstr[0], "+"); + strcat(bmvstr[1], "+"); + strcat(bmvstr[2], "+"); + } + } + else + bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = '\0'; +} + + + + +#ifndef QUIETBOOKGEN +void +bkdisplay (s, cnt, moveno) + char *s; + int cnt; + int moveno; +{ + static short pnt; + struct leaf far *node; + int r, c, l; + + pnt = TrPnt[2]; + printf ("matches = %d\n", cnt); + printf ("inout move is :%s: move number %d side %s\n", + s, moveno / 2 + 1, (moveno & 1) ? "white" : "black"); +#ifndef SEMIQUIETBOOKGEN + printf ("legal moves are \n"); + while (pnt < TrPnt[3]) + { + node = &Tree[pnt++]; + if ( is_promoted[board[node->f]] ) + Balgbr (node->f | 0x80, node->t, (short) node->flags); + else + Balgbr (node->f, node->t, (short) node->flags); + printf ("%s %s %s\n", + bmvstr[0], bmvstr[1], bmvstr[2]); + } + printf ("\n current board is\n"); + for (r = (NO_ROWS-1); r >= 0; r--) + { + for (c = 0; c <= (NO_COLS-1); c++) + { char pc; + l = locn (r, c); + pc = (is_promoted[board[l]] ? '+' : ' '); + if (color[l] == neutral) + printf (" -"); + else if (color[l] == black) + printf ("%c%c", pc, qxx[board[l]]); + else + printf ("%c%c", pc, pxx[board[l]]); + } + printf ("\n"); + } + printf ("\n"); + { + short color; + for (color = black; color <= white; color++) + { short piece, c; + printf((color==black)?"black ":"white "); + for (piece = pawn; piece <= king; piece++) + if (c = Captured[color][piece]) + printf("%i%c ",c,pxx[piece]); + printf("\n"); + }; + } +#endif /* SEMIQUIETBOOKGEN */ +} + +#endif /* QUIETBOOKGEN */ + +int +BVerifyMove (char *s, short unsigned int *mv, int moveno) + + /* + * Compare the string 's' to the list of legal moves available for the + * opponent. If a match is found, make the move on the board. + */ + +{ + static short pnt, tempb, tempc, tempsf, tempst, cnt; + static struct leaf xnode; + struct leaf far *node; + + *mv = 0; + cnt = 0; + MoveList (opponent, 2, -2, true); + pnt = TrPnt[2]; + while (pnt < TrPnt[3]) + { + node = &Tree[pnt++]; + if ( is_promoted[board[node->f]] ) + Balgbr (node->f | 0x80, node->t, (short) node->flags); + else + Balgbr (node->f, node->t, (short) node->flags); + if (strcmp (s, bmvstr[0]) == 0 || strcmp (s, bmvstr[1]) == 0 || + strcmp (s, bmvstr[2]) == 0) + { + cnt++; + xnode = *node; + } + } + if (cnt == 1) + { short blockable; + MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore); + if (SqAtakd (PieceList[opponent][0], computer, &blockable)) + { + UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst); + /* Illegal move in check */ +#if !defined QUIETBOOKGEN +#ifdef XSHOGI + printf ("Illegal move (in check)"); +#else + printf (CP[77]); +#endif + printf ("\n"); + bkdisplay (s, cnt, moveno); +#endif + return (false); + } + else + { + *mv = (xnode.f << 8) | xnode.t; + if ( is_promoted[board[xnode.t]] ) + Balgbr (xnode.f | 0x80, xnode.t, false); + else + Balgbr (xnode.f, xnode.t, false); + return (true); + } + } + /* Illegal move */ +#if !defined QUIETBOOKGEN +#ifdef XSHOGI + printf ("Illegal move (no match) %s\n", s); +#else + printf (CP[75], s); +#endif + bkdisplay (s, cnt, moveno); +#endif + return (false); +} + +void +RESET (void) + + /* + * Reset the board and other variables to start a new game. + */ + +{ + short int l; + + flag.illegal = flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false; + flag.material = flag.coords = flag.hash = flag.easy = flag.beep = flag.rcptr = true; + flag.stars = flag.shade = flag.back = flag.musttimeout = false; + flag.gamein = false; + GenCnt = 0; + GameCnt = 0; + CptrFlag[0] = TesujiFlag[0] = false; + opponent = black; + computer = white; + for (l = 0; l < NO_SQUARES; l++) + { + board[l] = Stboard[l]; + color[l] = Stcolor[l]; + Mvboard[l] = 0; + } + ClearCaptured (); + InitializeStats (); + hashbd = hashkey = 0; +} + +static +int +Vparse (FILE * fd, USHORT *mv, USHORT *flags, USHORT side, int moveno) +{ + int c, i; + char s[255]; + + *flags = 0; + + while (true) + { + + while ((c = getc (fd)) == ' ' || c == '!' || c == '/' || c == '\n'); + + if ( c == '(' ) + { /* amount of time spent for the last move */ + while ((c = getc(fd)) != ')' && c != EOF); + if ( c == ')' ) + while ((c = getc (fd)) == ' ' || c == '\n'); + } + + if (c == '[') + { /* comment for the actual game */ + while ( (c = getc(fd)) != ']' && c != EOF ); + if ( c == ']' ) + while ((c = getc (fd)) == ' ' || c == '\n'); + } + + if (c == '\r') + continue; + + if (c == '#') + { /* comment */ + do + { + c = getc (fd); + if (c == '\r') + continue; + /* goes to end of line */ + if (c == '\n') + { + return 0; + } + if (c == EOF) + return -1; + } + while (true); + } + + s[i = 0] = (char) c; + + while ( c >= '0' && c <= '9' ) + { + c = getc(fd); + s[++i] = (char) c; + } + + if ( c == '.' ) + { + while ((c = getc (fd)) == ' ' || c == '.' || c == '\n'); + s[i = 0] = (char) c; + } + + while ((c = getc (fd)) != '?' && c != '!' && c != ' ' && c != '(' && c != '\n' && c != '\t' && c != EOF) + { + if (c == '\r') + continue; + if (c != 'x' && c != '-' && c != ',' && c != ';' && c != '=') + s[++i] = (char) c; + } + s[++i] = '\0'; + + if ( c == '(' ) + { + while ((c = getc(fd)) != ')' && c != EOF); + if ( c == ')' ) + c = getc(fd); + } + + if (c == EOF) + return (-1); + + if (s[0] == '#') + { + while (c != '\n' && c != EOF) + c = getc (fd); + if (c == EOF) + return -1; + else + return (0); + } + + if (strcmp (s, "draw") == 0) + continue; + else if (strcmp (s, "1-0") == 0) + continue; + else if (strcmp (s, "0-1") == 0) + continue; + else if (strcmp (s, "Resigns") == 0) + continue; + else if (strcmp (s, "Resigns.") == 0) + continue; + else if (strcmp (s, "Sennichite") == 0) + continue; + else if (strcmp (s, "Sennichite.") == 0) + continue; + else if (strcmp (s, "Jishogi") == 0) + continue; + else if (strcmp (s, "Jishogi.") == 0) + continue; + + bhashkey = hashkey; + bhashbd = hashbd; + + i = BVerifyMove (s, mv, moveno); + + if (c == '?') + { /* Bad move, not for the program to play */ + *flags |= BADMOVE; /* Flag it ! */ + while ((c = getc (fd)) == '?' || c == '!' || c == '/'); + } +#ifdef EASY_OPENINGS + else if (c == '~') + { /* Do not use by computer */ + *flags |= BADMOVE; /* Flag it ! */ + while ((c = getc (fd)) == '?' || c == '!' || c == '/'); + } +#endif + else if (c == '!') + { /* Good move */ + *flags |= GOODMOVE; /* Flag it ! */ + while ((c = getc (fd)) == '?' || c == '!' || c == '/'); + } + else if (c == '\r') + c = getc (fd); + + if ( c == '(' ) + while ((c = getc(fd)) != ')' && c != EOF); + + if (!i) + { + /* flush to start of next */ + while ((c = getc (fd)) != '#' && c != EOF); + if (c == EOF) + return -1; + else + { + ungetc (c, fd); + return i; + } + } + + return (i); + } +} + + +static struct gdxadmin ADMIN; +struct gdxadmin B; + +static struct gdxdata DATA; + + + +/* lts(l) returns most significant 16 bits of l */ + +#ifdef LONG64 +#define lts(x) (USHORT)(((x>>48)&0xfffe)|side) +#else +#if defined THINK_C || defined USE_LTSIMP +static USHORT ltsimp (long x) +{ USHORT n; + n = (((x>>16)&0xfffe)); +#if 0 + printf("x=0x%lx lts(x)=0x%x\n",x,n); +#endif + return(n); +} +#define lts(x) (USHORT)(ltsimp(x) | side) +#else +#define lts(x) (USHORT)(((x>>16)&0xfffe) | side) +#endif +#endif + + +/* #define HashValue(l) lts(l) */ +#define HashValue(l) (USHORT)(l & 0xffff) + + +static int gfd; + + +static ULONG currentoffset; + + +#define MAXOFFSET(B) ((B.booksize-1)*sizeof_gdxdata + sizeof_gdxadmin) + +#define HashOffset(hashkey,B) { \ + currentoffset = ((ULONG)hashkey % B.booksize)*sizeof_gdxdata + sizeof_gdxadmin; \ +} + +#define NextOffset(B) { \ + currentoffset += sizeof_gdxdata; \ + if (currentoffset > B.maxoffset) \ + currentoffset = sizeof_gdxadmin; \ +} + + + + +#define WriteAdmin() { \ + lseek (gfd, 0, 0); \ + write (gfd, (char *)&ADMIN, sizeof_gdxadmin); \ +} + +#define WriteData() { \ + if ( mustwrite ) { \ + lseek (gfd, currentoffset, 0); \ + write (gfd, (char *)&DATA, sizeof_gdxdata); \ + mustwrite = false; \ + } \ +} + +static int ReadAdmin(void) { + lseek (gfd, 0, 0); + return (sizeof_gdxadmin == read (gfd, (char *)&ADMIN, sizeof_gdxadmin)); +} + +static int ReadData(struct gdxdata *DATA) { + lseek (gfd, currentoffset, 0); + return (sizeof_gdxdata == read (gfd, (char *)DATA, sizeof_gdxdata)); +} + + +void +GetOpenings (void) + + /* + * Read in the Opening Book file and parse the algebraic notation for a move + * into an unsigned integer format indicating the from and to square. Create + * a linked list of opening lines of play, with entry->next pointing to the + * next line and entry->move pointing to a chunk of memory containing the + * moves. More Opening lines of up to 100 half moves may be added to + gnuchess.book. But now its a hashed table by position which yields a move + * or moves for each position. It no longer knows about openings per say only + * positions and recommended moves in those positions. + */ +{ + short int i; + char opening[80]; + char msg[80]; + int mustwrite = false, first; + unsigned short xside, side; + short int c; + USHORT mv, flags; unsigned int x; + unsigned int games = 0; + LONG collisions = 0; + + FILE *fd; + + if ((fd = fopen (bookfile, "r")) == NULL) + fd = fopen ("gnushogi.tbk", "r"); + if (fd != NULL) + { + /* yes add to book */ + /* open book as writer */ + gfd = open (binbookfile, O_RDONLY | O_BINARY); + if (gfd >= 0) + { + if ( ReadAdmin() ) + { + B.bookcount = ADMIN.bookcount; + B.booksize = ADMIN.booksize; + B.maxoffset = ADMIN.maxoffset; + if (B.booksize && !(B.maxoffset == MAXOFFSET(B))) + { + printf ("bad format %s\n", binbookfile); + exit (1); + } + } + else + { + printf ("bad format %s\n", binbookfile); + exit (1); + } + close (gfd); + gfd = open (binbookfile, O_RDWR | O_BINARY); + + } + else + { +#if defined THINK_C || defined MSDOS + gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY); +#else + gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY, 0644); +#endif + ADMIN.bookcount = B.bookcount = 0; + ADMIN.booksize = B.booksize = booksize; + B.maxoffset = ADMIN.maxoffset = MAXOFFSET(B); + DATA.hashbd = 0; + DATA.hashkey = 0; + DATA.bmove = 0; + DATA.flags = 0; + DATA.hint = 0; + DATA.count = 0; + write (gfd, (char *)&ADMIN, sizeof_gdxadmin); + printf ("creating bookfile %s %ld %d\n", binbookfile, B.maxoffset, B.booksize); + for (x = 0; x < B.booksize; x++) + { + write (gfd, (char *)&DATA, sizeof_gdxdata); + } + + + } + if (gfd >= 0) + { + + + /* setvbuf(fd,buffr,_IOFBF,2048); */ + side = black; + xside = white; + hashbd = hashkey = 0; + i = 0; + + while ((c = Vparse (fd, &mv, &flags, side, i)) >= 0) + { + if (c == 1) + { + + /* + * if not first move of an opening and first + * time we have seen it save next move as + * hint + */ + i++; + if (i < bookmaxply + 2) + { + if (i > 1 && !(flags & BADMOVE)) { + DATA.hint = mv; + } + if (i < bookmaxply + 1) + { + /* + * see if this position and + * move already exist from + * some other opening + */ + + WriteData(); + HashOffset(bhashkey,B); + first = true; + while (true) { + if (!ReadData(&DATA)) break; /* corrupted binbook file */ + if (DATA.bmove == 0) break; /* free entry */ + if (DATA.hashkey == HashValue(bhashkey) && DATA.hashbd == bhashbd) { + if (DATA.bmove == mv) { + /* + * yes so just bump count - count is + * used to choose opening move in + * proportion to its presence in the book + */ + DATA.count++; + DATA.flags |= flags; + mustwrite = true; + break; + } else { + if ( first ) collisions++; + if (DATA.flags & LASTMOVE) { + DATA.flags &= (~LASTMOVE); + mustwrite = true; + WriteData(); + } + } + } + NextOffset(B); + first = false; + } + + /* + * doesn`t exist so add it to + * the book + */ + if (!mustwrite) + { + B.bookcount++; +#if !defined XSHOGI +#if defined THINK_C || defined MSDOS + if (B.bookcount % 100 == 0) +#else + if (B.bookcount % 1000 == 0) +#endif + printf ("%d rec %d openings processed\n", B.bookcount, games); +#endif + /* initialize a record */ + DATA.hashbd = bhashbd; + DATA.hashkey = HashValue(bhashkey); + DATA.bmove = mv; + DATA.flags = flags | LASTMOVE; + DATA.count = 1; + DATA.hint = 0; + mustwrite = true; + } + } + } + computer = opponent; + opponent = computer ^ 1; + + xside = side; + side = side ^ 1; + } + else if (i > 0) + { + /* reset for next opening */ + games++; + WriteData(); + RESET (); + i = 0; + side = black; + xside = white; + + } + } + WriteData(); + fclose (fd); + /* write admin rec with counts */ + ADMIN.bookcount = B.bookcount; + WriteAdmin(); + + close (gfd); + } + } + if (binbookfile != NULL) + { + /* open book as reader */ + gfd = open (binbookfile, O_RDONLY | O_BINARY); + if (gfd >= 0) + { + if ( ReadAdmin() && (!ADMIN.booksize || ADMIN.maxoffset == MAXOFFSET(ADMIN)) ) + { + B.bookcount = ADMIN.bookcount; + B.booksize = ADMIN.booksize; + B.maxoffset = ADMIN.maxoffset; + } + else + { + printf ("bad format %s\n", binbookfile); + exit (1); + } + + } + else + { + B.bookcount = 0; + B.booksize = booksize; + + } + +#if !defined XSHOGI + sprintf (msg, CP[213], B.bookcount, B.booksize); + ShowMessage (msg); + /* printf("%ld collisions\n", collisions); */ +#endif + } + /* set every thing back to start game */ + Book = BOOKFAIL; + RESET (); + /* now get ready to play */ + if (!B.bookcount) + { +#if !defined XSHOGI + ShowMessage (CP[212]); +#endif + Book = 0; + } +} + + +int +OpeningBook (unsigned short *hint, short int side) + + /* + * Go thru each of the opening lines of play and check for a match with the + * current game listing. If a match occurs, generate a random number. If this + * number is the largest generated so far then the next move in this line + * becomes the current "candidate". After all lines are checked, the + * candidate move is put at the top of the Tree[] array and will be played by + * the program. Note that the program does not handle book transpositions. + */ + +{ + unsigned short r, m; + int possibles = TrPnt[2] - TrPnt[1]; + + gsrand ((unsigned int) time ((long *) 0)); + m = 0; + + /* + * find all the moves for this position - count them and get their + * total count + */ + { + USHORT i, x; + USHORT rec = 0; + USHORT summ = 0; + USHORT h = 0, b = 0; + struct gdxdata OBB[128]; + if (B.bookcount == 0) + { + Book--; + return false; + } + x = 0; + HashOffset(hashkey,B); +#ifdef BOOKTEST + printf("looking for book move, bhashbd = 0x%lx bhashkey = 0x%x\n", (ULONG)hashbd, HashValue(hashkey)); +#endif + while (true) + { + if (!ReadData(&OBB[x])) break; + if (OBB[x].bmove == 0) break; +#ifdef BOOKTEST + printf("compare with bhashbd = 0x%lx bhashkey = 0x%x\n", OBB[x].hashbd, OBB[x].hashkey); +#endif + if (OBB[x].hashkey == HashValue(hashkey) && OBB[x].hashbd == (ULONG)hashbd) + { + x++; + if (OBB[x-1].flags & LASTMOVE) break; + } + NextOffset(B); + } +#ifdef BOOKTEST + printf("%d book move(s) found.\n",x); +#endif + if (x == 0) + { + Book--; + return false; + } + for (i = 0; i < x; i++) + { + if (OBB[i].flags & BADMOVE) + { + m = OBB[i].bmove; + /* is the move is in the MoveList */ + for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++) + { + if (((Tree[b].f << 8) | Tree[b].t) == m) + { + + if (--possibles) + Tree[b].score = DONTUSE; + break; + } + } + } + else + { +#if defined BOOKTEST + char s[20]; + movealgbr(m = OBB[i].bmove,s); + printf("finding book move: %s\n",s); +#endif + summ += OBB[i].count; + } + } + if (summ == 0) + { + Book--; + return false; + } + + r = (urand () % summ); + for (i = 0; i < x; i++) + if (!(OBB[i].flags & BADMOVE) ){ + if( r < OBB[i].count) + { + rec = i; + break; + } + else + r -= OBB[i].count; + } + + h = OBB[rec].hint; + m = OBB[rec].bmove; + /* make sure the move is in the MoveList */ + for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++) + { + if (((Tree[b].f << 8) | Tree[b].t) == m) + { + Tree[b].flags |= book; + Tree[b].score = 0; + break; + } + } + /* Make sure its the best */ + + pick (TrPnt[1], TrPnt[2] - 1); + if (Tree[TrPnt[1]].score) + { + /* no! */ + Book--; + return false; + } + /* ok pick up the hint and go */ + *hint = h; + return true; + } + Book--; + return false; +} + + + diff --git a/src/book.h b/src/book.h new file mode 100644 index 0000000..c987634 --- /dev/null +++ b/src/book.h @@ -0,0 +1,60 @@ +/* + * book.h - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software + * Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) any later + * version. + * + * GNU Shogi 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 + * GNU Shogi; see the file COPYING. If not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + + +struct gdxadmin { + ULONG bookcount; + ULONG booksize; + ULONG maxoffset; +}; + +extern struct gdxadmin B; + + +#define GOODMOVE 0x1000 +#define BADMOVE 0x0100 +#define LASTMOVE 0x0010 + +struct gdxdata +{ + ULONG hashbd; + USHORT hashkey; + USHORT bmove; + USHORT flags; /* flags BADMOVE, GOODMOVE, LASTMOVE */ + USHORT hint; + USHORT count; +}; + + +#define sizeof_gdxadmin sizeof(struct gdxadmin) +#define sizeof_gdxdata sizeof(struct gdxdata) + + + + diff --git a/src/dspcom.c b/src/dspcom.c new file mode 100644 index 0000000..084fa56 --- /dev/null +++ b/src/dspcom.c @@ -0,0 +1,2147 @@ +/* + * dspcom.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" + +#if defined HASGETTIMEOFDAY +#include +#endif +char mvstr[4][6]; +char *InPtr; +int InBackground = false; + + +#include +#include +#if defined THINK_C +#include +#define BOOKTEST +#elif defined MSDOS +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#if defined DEBUG || defined DEBUG_EVAL +short debug_eval = false; +FILE *debug_eval_file = NULL; +short debug_moves = false; +#endif + + +#if defined DEBUG || defined BOOKTEST || defined DEBUG_EVAL + +void +movealgbr (short int m, char *s) +{ + unsigned int f, t; + short piece = 0, flag = 0; + if ( m == 0 ) + { + strcpy(s,"none"); + return; + } + f = (m >> 8) & 0x7f; + t = m & 0xff; + if ( f > NO_SQUARES ) + { piece = f - NO_SQUARES; + if ( piece > NO_PIECES ) piece -= NO_PIECES; + flag = (dropmask | piece); + } + if ( t & 0x80 ) + { + flag |= promote; + t &= 0x7f; + } + if ( flag & dropmask ) + { + *s = pxx[piece]; s++; + *s = '*'; s++; + *s = cxx[column (t)]; s++; + *s = rxx[row (t)]; s++; + } + else + { + *s = cxx[column (f)]; s++; + *s = rxx[row (f)]; s++; + *s = cxx[column (t)]; s++; + *s = rxx[row (t)]; s++; + if ( flag & promote ) + { + *s = '+'; s++; + } + } + if (m & 0x8000) + { + *s = '?'; s++; + } + *s = '\0'; +} + +#endif + + +void +algbr (short int f, short int t, short int flag) + + +/* + * Generate move strings in different formats. + */ + +{ + int m3p; + + if ( f > NO_SQUARES ) + { short piece; + piece = f - NO_SQUARES; + if ( f > (NO_SQUARES+NO_PIECES) ) + piece -= NO_PIECES; + flag = (dropmask | piece); + } + if ( (t & 0x80) != 0 ) + { + flag |= promote; + t &= 0x7f; + } + if ( f == t && (f != 0 || t != 0) ) + { +#if !defined BAREBONES + printz("error in algbr: FROM=TO=%d, flag=0x%4x\n",t,flag); +#endif + mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0'; + } + else + if ( (flag & dropmask) != 0 ) + { short piece = flag & pmask; + mvstr[0][0] = pxx[piece]; + mvstr[0][1] = '*'; + mvstr[0][2] = cxx[column (t)]; + mvstr[0][3] = rxx[row (t)]; + mvstr[0][4] = '\0'; + strcpy (mvstr[1], mvstr[0]); + strcpy (mvstr[2], mvstr[0]); + strcpy (mvstr[3], mvstr[0]); + } + else + if (f != 0 || t != 0) + { + /* algebraic notation */ + mvstr[0][0] = cxx[column (f)]; + mvstr[0][1] = rxx[row (f)]; + mvstr[0][2] = cxx[column (t)]; + mvstr[0][3] = rxx[row (t)]; + mvstr[0][4] = mvstr[3][0] = '\0'; + mvstr[1][0] = pxx[board[f]]; + + mvstr[2][0] = mvstr[1][0]; + mvstr[2][1] = mvstr[0][1]; + + mvstr[2][2] = mvstr[1][1] = mvstr[0][2]; /* to column */ + mvstr[2][3] = mvstr[1][2] = mvstr[0][3]; /* to row */ + mvstr[2][4] = mvstr[1][3] = '\0'; + strcpy (mvstr[3], mvstr[2]); + mvstr[3][1] = mvstr[0][0]; + if (flag & promote) + { + strcat(mvstr[0], "+"); + strcat(mvstr[1], "+"); + strcat(mvstr[2], "+"); + strcat(mvstr[3], "+"); + } + } + else + mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0'; +} + + +int +VerifyMove (char *s, VerifyMove_mode iop, short unsigned int *mv) + +/* + * Compare the string 's' to the list of legal moves available for the + * opponent. If a match is found, make the move on the board. + */ + +{ + static short pnt, tempb, tempc, tempsf, tempst, cnt; + static struct leaf xnode; + struct leaf far *node; + char buffer[60],buf2[60]; + short i,l, local_flags; + + /* check and remove quality flags */ + for (i=local_flags=0,l=strlen(s); if, node->t, (short) node->flags); + if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 || + strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0) + { + cnt++; + xnode = *node; + } + } + if (cnt == 1 && xnode.score > DONTUSE) + { + short blocked; + MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore); + if (SqAtakd (PieceList[opponent][0], computer, &blocked)) + { + UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst); +#ifdef NONDSP +/* Illegal move in check */ +#ifdef XSHOGI + printz ("Illegal move (in check) %s",mvstr[0]); +#else + printz (CP[77], mvstr[0]); +#endif + printz ("\n"); +#else +/* Illegal move in check */ + sprintf (buffer, CP[77], s); + ShowMessage (buffer); +#endif + return (false); + } + else + { + if (iop == VERIFY_AND_TRY_MODE) + return (true); + UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags); + GameList[GameCnt].depth = GameList[GameCnt].score = 0; + GameList[GameCnt].nodes = 0; + ElapsedTime (COMPUTE_AND_INIT_MODE); + GameList[GameCnt].time = (short) (et+50)/100; + GameList[GameCnt].flags |= local_flags; + if (TCflag) + { + TimeControl.clock[opponent] -= et; + timeopp[oppptr] = et; + --TimeControl.moves[opponent]; + } + *mv = (xnode.f << 8) | xnode.t; + algbr (xnode.f, xnode.t, false); + /* in force mode, check for mate conditions */ + if ( flag.force ) + { + if ( IsCheckmate(opponent ^ 1,-1,-1) ) + { char buf[20],buf2[20]; + sprintf(buf,"%s mates!\n",ColorStr[opponent]); + ShowMessage(buf); + flag.mate = true; + } + } + return (true); + } + } +#ifdef NONDSP +/* Illegal move */ +#ifdef XSHOGI + printz ("Illegal move (no match) %s\n", s); +#else + printz (CP[75], s); +#endif +#ifdef DEBUG8 + if (1) + { + FILE *D; + int r, c, side, l; + extern unsigned short int PrVar[]; + D = fopen ("/tmp/DEBUG", "a+"); + pnt = TrPnt[2]; + fprintf (D, "resp = %d\n", ResponseTime); + fprintf (D, "iop = %d\n", iop); + fprintf (D, "matches = %d\n", cnt); + algbr (hint >> 8, hint & 0xff, (short) 0); + fprintf (D, "hint %s\n", mvstr[0]); + fprintf (D, "inout move is %s\n", s); + for (r = 1; PrVar[r]; r++) + { + algbr (PrVar[r] >> 8, PrVar[r] & 0xff, (short) 0); + fprintf (D, " %s", mvstr[0]); + } + fprintf (D, "\n"); + fprintf (D, "legal move are \n"); + while (pnt < TrPnt[3]) + { + node = &Tree[pnt++]; + algbr (node->f, node->t, (short) node->flags); + fprintf (D, "%s %s %s %s\n", mvstr[0], mvstr[1], mvstr[2], mvstr[3]); + } + debug_position (D); + fclose (D); + abort (); + } +#endif +#else +/* Illegal move */ + sprintf(buffer,CP[76],s); + ShowMessage (buffer); +#endif +#if !defined BAREBONES + if (cnt > 1) { + sprintf(buffer,CP[32],s); + ShowMessage(buffer); + } +#endif + return (false); +} + + + +static int +parser (char *f, int side, short *fpiece) +{ + int c1, r1, c2, r2; + short i, p = false; + if ( *f == '+' ) + f++, p = true; + for ( i = 1, *fpiece = no_piece; i -1; i--) + { + fgets (fname, 256, fd); + p = &fname[2]; + InPtr = &fname[23]; + for (j = 0; j < NO_COLS; j++) + { + sq = i * NO_COLS + j; + isp = ( *p == '+' ); + p++; + if (*p == '-') + { + board[sq] = no_piece; + color[sq] = neutral; + } + else + { + for (c = 0; c < NO_PIECES; c++) + { + if (*p == pxx[c]) + { + if ( isp ) + board[sq] = promoted[c]; + else + board[sq] = unpromoted[c]; + color[sq] = white; + } + } + for (c = 0; c < NO_PIECES; c++) + { + if (*p == qxx[c]) + { + if ( isp ) + board[sq] = promoted[c]; + else + board[sq] = unpromoted[c]; + color[sq] = black; + } + } + } + p++; + Mvboard[sq] = atoi (InPtr); + skip (); + } + } + fgets (fname, 256, fd); /* empty */ + fgets (fname, 256, fd); /* 9 8 7 ... */ + fgets (fname, 256, fd); /* empty */ + fgets (fname, 256, fd); /* p l n ... */ + ClearCaptured (); + for ( side = 0; side <= 1; side++ ) { + fgets (fname, 256, fd); + InPtr = fname; + skip (); + skipb (); + Captured[side][pawn] = atoi (InPtr); + skip (); + Captured[side][lance] = atoi (InPtr); + skip (); + Captured[side][knight] = atoi (InPtr); + skip (); + Captured[side][silver] = atoi (InPtr); + skip (); + Captured[side][gold] = atoi (InPtr); + skip (); + Captured[side][bishop] = atoi (InPtr); + skip (); + Captured[side][rook] = atoi (InPtr); + skip (); + Captured[side][king] = atoi (InPtr); + } + GameCnt = 0; + flag.regularstart = true; + Book = BOOKFAIL; + fgets (fname, 256, fd); /* empty */ + fgets (fname, 256, fd); /* move score ... */ + while (fgets (fname, 256, fd)) + { + struct GameRec far *g; + int side = computer; + short f; + + side = side ^ 1; + ++GameCnt; + InPtr = fname; + skipb (); + g = &GameList[GameCnt]; + g->gmove = parser (InPtr, side, &g->fpiece); + skip (); + g->score = atoi (InPtr); + skip (); + g->depth = atoi (InPtr); + skip (); + g->nodes = atol (InPtr); + skip (); + g->time = atol (InPtr); + skip (); + g->flags = c = atoi (InPtr); + skip (); + g->hashkey = strtol (InPtr, (char **) NULL, 16); + skip (); + g->hashbd = strtol (InPtr, (char **) NULL, 16); + if (c & capture) + { short i, piece; + + skip (); + for (piece = no_piece, i = 0; i < NO_PIECES; i++) + if (pxx[i] == *InPtr) { + piece = i; + break; + } + skip (); + g->color = ((*InPtr == CP[119][0]) ? white : black); + skip (); + g->piece = (*InPtr == '+' ? promoted[piece] : unpromoted[piece]); + } + else + { + g->color = neutral; + g->piece = no_piece; + } + } + if (TimeControl.clock[black] > 0) + TCflag = true; + fclose (fd); + } + ZeroRPT (); + InitializeStats (); + UpdateDisplay (0, 0, 1, 0); + Sdepth = 0; + hint = 0; +} + + +void +SaveGame (void) +{ + FILE *fd; + char fname[256]; + short sq, i, c, f, t; + char p; + short side, piece; + char empty[2] = "\n"; + + if (savefile[0]) + strcpy (fname, savefile); + else + { +/* Enter file name*/ + ShowMessage (CP[63]); + scanz ("%s", fname); + } + if (fname[0] == '\0') +/* shogi.000 */ + strcpy (fname, CP[137]); + if ((fd = fopen (fname, "w")) != NULL) + { + char *b, *w; + b = w = CP[74]; + if (computer == white) + w = CP[141]; + if (computer == black) + b = CP[141]; + fprintf (fd, CP[37], w, b, Game50, + flag.force ? "force" : ""); + fprintf (fd, empty); + fprintf (fd, CP[111], TCflag, OperatorTime); + fprintf (fd, CP[117], + TimeControl.clock[black], TimeControl.moves[black], + TimeControl.clock[white], TimeControl.moves[white]); + fprintf (fd, empty); + for (i = NO_ROWS-1; i > -1; i--) + { + fprintf (fd, "%c ", 'i' - i); + for (c = 0; c < NO_COLS; c++) + { + sq = i * NO_COLS + c; + piece = board[sq]; + p = is_promoted[piece] ? '+' : ' '; + fprintf (fd, "%c", p); + switch (color[sq]) + { + case white: + p = pxx[piece]; + break; + case black: + p = qxx[piece]; + break; + default: + p = '-'; + } + fprintf (fd, "%c", p); + } + fprintf (fd, " "); + for (f = i * NO_COLS; f < i * NO_COLS + NO_ROWS; f++) + fprintf (fd, " %d", Mvboard[f]); + fprintf (fd, "\n"); + } + fprintf (fd, empty); + fprintf (fd, " 9 8 7 6 5 4 3 2 1\n"); + fprintf (fd, empty); + fprintf (fd, " p l n s g b r k\n"); + for ( side = 0; side <= 1; side++ ) { + fprintf (fd, "%c", (side == black) ? 'B' : 'W'); + fprintf (fd, " %2d", Captured[side][pawn]); + fprintf (fd, " %2d", Captured[side][lance]); + fprintf (fd, " %2d", Captured[side][knight]); + fprintf (fd, " %2d", Captured[side][silver]); + fprintf (fd, " %2d", Captured[side][gold]); + fprintf (fd, " %2d", Captured[side][bishop]); + fprintf (fd, " %2d", Captured[side][rook]); + fprintf (fd, " %2d", Captured[side][king]); + fprintf (fd, "\n"); + } + fprintf (fd, empty); + fprintf (fd, CP[126]); + for (i = 1; i <= GameCnt; i++) + { + struct GameRec far *g = &GameList[i]; + + f = g->gmove >> 8; + t = (g->gmove & 0xFF); + algbr (f, t, g->flags); +#ifdef THINK_C + fprintf (fd, "%c%c%-5s %6d %5d %7ld %6ld %5d 0x%08lx 0x%08lx", +#else + fprintf (fd, "%c%c%-5s %6d %5d %7ld %6ld %5d 0x%08x 0x%08x", +#endif + (f>NO_SQUARES ? ' ' : (is_promoted[g->fpiece] ? '+' : ' ')), + pxx[g->fpiece], + (f>NO_SQUARES ? &mvstr[0][1] : mvstr[0]), + g->score, g->depth, + g->nodes, g->time, g->flags, + g->hashkey, g->hashbd); + if ( g->piece != no_piece ) + fprintf (fd, " %c %s %c\n", + pxx[g->piece], ColorStr[g->color], + (is_promoted[g->piece] ? '+' : ' ')); + else + fprintf (fd, "\n"); + } + fclose (fd); +/* Game saved */ + ShowMessage (CP[70]); + } + else + /*ShowMessage ("Could not open file");*/ + ShowMessage (CP[48]); +} + + + + +#if !defined XSHOGI + + +void +GetXGame (void) +{ + FILE *fd; + char fname[256], *p; + int c, i, j; + short sq; + short side, isp; +/* Enter file name */ + ShowMessage (CP[63]); + scanz ("%s", fname); + if (fname[0] == '\0') +/* XSHOGI.position.read*/ + strcpy (fname, CP[205]); + if ((fd = fopen (fname, "r")) != NULL) + { + NewGame (); + flag.regularstart = false; + Book = false; + /* xshogi position file ... */ + fgets (fname, 256, fd); +#ifdef notdef + fname[6] = '\0'; + if (strcmp (fname, CP[206])) + return; +#endif + /* -- empty line -- */ + fgets (fname, 256, fd); + /* -- empty line -- */ + fgets (fname, 256, fd); + for (i = NO_ROWS-1; i > -1; i--) + { + fgets (fname, 256, fd); + p = fname; + for (j = 0; j < NO_COLS; j++) + { + sq = i * NO_COLS + j; + isp = ( *p == '+' ); + p++; + if (*p == '.') + { + board[sq] = no_piece; + color[sq] = neutral; + } + else + { + for (c = 0; c < NO_PIECES; c++) + { + if (*p == qxx[c]) + { + if ( isp ) + board[sq] = promoted[c]; + else + board[sq] = unpromoted[c]; + color[sq] = white; + } + } + for (c = 0; c < NO_PIECES; c++) + { + if (*p == pxx[c]) + { + if ( isp ) + board[sq] = promoted[c]; + else + board[sq] = unpromoted[c]; + color[sq] = black; + } + } + } + p++; + } + } + ClearCaptured (); + for ( side = 0; side <= 1; side++ ) { + fgets (fname, 256, fd); + InPtr = fname; + Captured[side][pawn] = atoi (InPtr); + skip (); + Captured[side][lance] = atoi (InPtr); + skip (); + Captured[side][knight] = atoi (InPtr); + skip (); + Captured[side][silver] = atoi (InPtr); + skip (); + Captured[side][gold] = atoi (InPtr); + skip (); + Captured[side][bishop] = atoi (InPtr); + skip (); + Captured[side][rook] = atoi (InPtr); + skip (); + Captured[side][king] = atoi (InPtr); + }; + if (fgets(fname, 256, fd) != NULL && strncmp(fname, "white", 5) == 0) + { + computer = black; + opponent = white; + xwndw = BXWNDW; + } + fclose (fd); + } + Game50 = 1; + ZeroRPT (); + InitializeStats (); + UpdateDisplay (0, 0, 1, 0); + Sdepth = 0; + hint = 0; +} + + +void +SaveXGame (void) +{ + FILE *fd; + char fname[256], *p; + int c, i, j; + short sq, piece; + short side, isp; +/* Enter file name */ + ShowMessage (CP[63]); + scanz ("%s", fname); + if (fname[0] == '\0') +/* XSHOGI.position.read*/ + strcpy (fname, CP[205]); + if ((fd = fopen (fname, "w")) != NULL) + { + /* xshogi position file ... */ + fputs("# xshogi position file -- \n", fd); + /* -- empty line -- */ + fputs("\n",fd); + /* -- empty line -- */ + fputs("\n", fd); + for (i = NO_ROWS-1; i > -1; i--) + { + p = fname; + for (j = 0; j < NO_COLS; j++) + { + sq = i * NO_COLS + j; + piece = board[sq]; + isp = is_promoted[piece]; + *p = (isp ? '+' : ' '); + p++; + if ( piece == no_piece ) { + *p = '.'; + } else if ( color[sq] == white ) { + *p = qxx[piece]; + } else { + *p = pxx[piece]; + } + p++; + } + *p++ = '\n';; + *p++ = '\0';; + fputs(fname, fd); + } + for ( side = 0; side <= 1; side++ ) { + sprintf(fname,"%d %d %d %d %d %d %d %d\n", + Captured[side][pawn], + Captured[side][lance], + Captured[side][knight], + Captured[side][silver], + Captured[side][gold], + Captured[side][bishop], + Captured[side][rook], + Captured[side][king]); + fputs(fname, fd); + }; + if ( computer == black ) { + fputs("white to play\n", fd); + } else { + fputs("black to play\n", fd); + } + fclose (fd); + } +} + + + +#endif /* !XSHOGI */ + + + + +#if !defined XSHOGI + + +void +BookSave (void) +{ + FILE *fd; + char fname[256], sflags[4]; + short sq, i, j, c, f, t; + char p; + short side, piece; + + if (savefile[0]) + strcpy (fname, savefile); + else + { +/* Enter file name*/ + ShowMessage (CP[63]); + scanz ("%s", fname); + } + + if (fname[0] == '\0') + return; + + if ((fd = fopen (fname, "a")) != NULL) + { + fprintf(fd,"#\n"); + for (i = 1; i <= GameCnt; i++) + { + struct GameRec far *g = &GameList[i]; + char mvnr[20], mvs[20]; + if (i % 2) + sprintf(mvnr,"%d.",(i+1)/2); + else + strcpy(mvnr,""); + f = g->gmove >> 8; + t = (g->gmove & 0xFF); + algbr (f, t, g->flags); + j = 0; + /* determine move quality string */ + if ( g->flags & goodmove ) + sflags[j++] = '!'; + if ( g->flags & badmove ) + sflags[j++] = '?'; +#ifdef EASY_OPENINGS + if ( g->flags & difficult ) + sflags[j++] = '~'; +#endif + sflags[j] = '\0'; + /* determine move string */ + if ( f>NO_SQUARES ) + sprintf(mvs,"%s%s ",&mvstr[0][1],sflags); + else + sprintf(mvs,"%c%c%c%c%c%s%s ", + mvstr[0][0], mvstr[0][1], + (g->flags & capture) ? 'x' : '-', + mvstr[0][2], mvstr[0][3], + (mvstr[0][4]=='+') ? "+" : "", + sflags); + fprintf (fd, "%s%s%c%s", + mvnr, + (f>NO_SQUARES ? "" : (is_promoted[g->fpiece] ? "+" : "")), + pxx[g->fpiece], + mvs); + if ( (i % 10) == 0) + fprintf (fd, "\n"); + } + if ( (i % 10) != 1) + fprintf (fd, "\n"); + fclose (fd); +/* Game saved */ + ShowMessage (CP[70]); + } + else + /*ShowMessage ("Could not open file");*/ + ShowMessage (CP[48]); +} + + +#endif /* !XSHOGI */ + + +void +ListGame (void) +{ + FILE *fd; + short i, f, t; +#ifndef MSDOS + time_t when; + char fname[256], dbuf[256]; +#else + char fname[256]; +#endif + + if (listfile[0]) + strcpy (fname, listfile); + else + { +#ifdef MSDOS + sprintf (fname, "shogi.lst"); +#else + time (&when); + strncpy (dbuf, ctime (&when), 20); + dbuf[7] = '\0'; + dbuf[10] = '\0'; + dbuf[13] = '\0'; + dbuf[16] = '\0'; + dbuf[19] = '\0'; +/* use format "CLp16.Jan01-020304B" when patchlevel is 16, + date is Jan 1 + time is 02:03:04 + program played white */ + sprintf (fname, "CLp%s.%s%s-%s%s%s%c", patchlevel, dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14, dbuf + 17, ColorStr[computer][0]); + /* replace space padding with 0 */ + for (i = 0; fname[i] != '\0'; i++) + if (fname[i] == ' ') + fname[i] = '0'; +#endif /* MSDOS */ + } + fd = fopen (fname, "w"); + if (!fd) + { + printf (CP[219], fname); + exit (1); + } + /*fprintf (fd, "gnushogi game %d\n", u);*/ + fprintf (fd, CP[161], version, patchlevel); + fprintf (fd, CP[10]); + fprintf (fd, CP[11]); + for (i = 1; i <= GameCnt; i++) + { + f = GameList[i].gmove >> 8; + t = (GameList[i].gmove & 0xFF); + algbr (f, t, GameList[i].flags); + if(GameList[i].flags & book) + fprintf (fd, "%c%c%-5s %5d Book%7ld %5d", + (f>NO_SQUARES ? ' ' : (is_promoted[GameList[i].fpiece] ? '+' : ' ')), + pxx[GameList[i].fpiece], + (f>NO_SQUARES ? &mvstr[0][1] : mvstr[0]), + GameList[i].score, + GameList[i].nodes, GameList[i].time); + else + fprintf (fd, "%c%c%-5s %5d %2d %7ld %5d", + (f>NO_SQUARES ? ' ' : (is_promoted[GameList[i].fpiece] ? '+' : ' ')), + pxx[GameList[i].fpiece], + (f>NO_SQUARES ? &mvstr[0][1] : mvstr[0]), + GameList[i].score, GameList[i].depth, + GameList[i].nodes, GameList[i].time); + if ((i % 2) == 0) + { + fprintf (fd, "\n"); +#ifdef DEBUG40 + if (computer == white) + fprintf (fd, " %d %d %d %d %d %d %d\n", + GameList[i].d1, + GameList[i].d2, + GameList[i].d3, + GameList[i].d4, + GameList[i].d5, + GameList[i].d6, + GameList[i].d7); + else + fprintf (fd, " %d %d %d %d %d %d %d\n", + GameList[i - 1].d1, + GameList[i - 1].d2, + GameList[i - 1].d3, + GameList[i - 1].d4, + GameList[i - 1].d5, + GameList[i - 1].d6, + GameList[i - 1].d7); +#endif + } + else + fprintf (fd, " "); + } + fprintf (fd, "\n\n"); + if (GameList[GameCnt].flags & draw) + { + fprintf (fd, CP[54], DRAW); + if ( DRAW == CP[101] ) + { short j; + fprintf (fd, "repetition by positions "); + for ( j = GameCnt-1; j >= Game50; j -= 2) + if ( GameList[j].hashkey == hashkey && + GameList[j].hashbd == hashbd ) + fprintf (fd, "%d ", j); + fprintf (fd, "\n"); + } + } + else if (GameList[GameCnt].score == -(SCORE_LIMIT+999)) + { + fprintf (fd, "%s\n", ColorStr[player ]); + } + else if (GameList[GameCnt].score == (SCORE_LIMIT+998)) + { + fprintf (fd, "%s\n", ColorStr[player ^ 1]); + } + fclose (fd); +} + + + +void +FlagMove (char c) +{ + switch (c) { + case '?' : + GameList[GameCnt].flags |= badmove; + break; + case '!' : + GameList[GameCnt].flags |= goodmove; + break; +#ifdef EASY_OPENINGS + case '~' : + GameList[GameCnt].flags |= difficult; + break; +#endif + } +} + + +void +Undo (void) + +/* + * Undo the most recent half-move. + */ + +{ + short f, t; + f = GameList[GameCnt].gmove >> 8; + t = GameList[GameCnt].gmove & 0x7F; + if ( f > NO_SQUARES ) + { /* the move was a drop */ + Captured[color[t]][board[t]]++; + board[t] = no_piece; + color[t] = neutral; + Mvboard[t]--; + } + else + { + if ( GameList[GameCnt].flags & promote ) + board[f] = unpromoted[board[t]]; + else + board[f] = board[t]; + color[f] = color[t]; + board[t] = GameList[GameCnt].piece; + color[t] = GameList[GameCnt].color; + if ( board[t] != no_piece ) + Captured[color[f]][unpromoted[board[t]]]--; + if (color[t] != neutral) + Mvboard[t]--; + Mvboard[f]--; + } + InitializeStats (); + + if (TCflag && (TCmoves>1)) + ++TimeControl.moves[color[f]]; + hashkey = GameList[GameCnt].hashkey; + hashbd = GameList[GameCnt].hashbd; + GameCnt--; + computer = computer ^ 1; + opponent = opponent ^ 1; + flag.mate = false; + Sdepth = 0; + player = player ^ 1; + ShowSidetoMove (); + UpdateDisplay (0, 0, 1, 0); + if (flag.regularstart) + Book = false; +} + + + +#if !defined XSHOGI + + +void +FlagString (unsigned short flags, char *s) +{ + short l,piece; + *s = '\0'; + if ( flags & promote ) + strcat (s, " promote"); + if ( flags & dropmask ) + strcat (s, " drop:"); + if ( piece = (flags & pmask) ) { + l=strlen(s); + if(is_promoted[piece]) + s[l++] = '+'; + s[l++] = pxx[piece]; + s[l]='\0'; + } + if ( flags & capture ) + strcat (s, " capture"); + if ( flags & exact ) + strcat (s, " exact"); + if ( flags & tesuji ) + strcat (s, " tesuji"); + if ( flags & check ) + strcat (s, " check"); + if ( flags & draw ) + strcat (s, " draw"); + if ( flags & stupid ) + strcat (s, " stupid"); + if ( flags & questionable ) + strcat (s, " questionable"); + if ( flags & kingattack ) + strcat (s, " kingattack"); + if ( flags & book ) + strcat (s, " book"); +} + + + +void + TestSpeed (void (*f) (short int side, short int ply, short int in_check, short int blockable), + unsigned j) +{ +#ifdef test + unsigned jj; +#endif + unsigned i; + long cnt, rate, t1, t2; +#ifdef HASGETTIMEOFDAY +struct timeval tv; +#endif + +#ifdef HASGETTIMEOFDAY + gettimeofday(&tv,NULL); + t1 = (tv.tv_sec*100+(tv.tv_usec/10000)); +#elif defined THINK_C || defined MSDOS + t1 = clocktime(); +#else + t1 = time (0); +#endif +#ifdef DEBUG_EVAL + debug_moves = true; +#endif + for (i = 0; i < j; i++) + { + f (opponent, 2, -1, true); +#ifdef test + for(jj=TrPnt[2];i 0 ) + znodes = rate; +#endif + /*printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);*/ +#ifdef NONDSP + printz (CP[91], cnt, rate); +#ifdef DEBUG9 + for (j = TrPnt[2]; j < TrPnt[3]; j++) + { + struct leaf far *node = &Tree[j]; + algbr (node->f, node->t, node->flags); +#ifdef DEBUG_EVAL + if ( debug_eval ) + { +#if defined FIELDBONUS || defined DROPBONUS + if ( node->score <= DONTUSE ) + fprintf (debug_eval_file, "%s %s %s %s DONTUSE", + mvstr[0], mvstr[1], mvstr[2], mvstr[3]); + else + fprintf (debug_eval_file, "%s %s %s %s score %d INC %d", + mvstr[0], mvstr[1], mvstr[2], mvstr[3],node->score,node->INCscore); +#else + if ( node->score <= DONTUSE ) + fprintf (debug_eval_file, "%s %s %s %s DONTUSE", + mvstr[0], mvstr[1], mvstr[2], mvstr[3]); + else + fprintf (debug_eval_file, "%s %s %s %s score %d", + mvstr[0], mvstr[1], mvstr[2], mvstr[3], node->score); +#endif + if ( node->flags ) + { char s[80]; + FlagString(node->flags, s); + fprintf(debug_eval_file,"%s",s); + } +#ifdef HISTORY + { short mv; + unsigned short hi0, hi1; + mv = (node->f << 8) | node->t; + if ( node->flags & promote ) mv |= 0x80; + hi0 = hindex(0,mv); + hi1 = hindex(1,mv); + fprintf (debug_eval_file, " mv=%x hi0=%x hi1=%x",mv, hi0, hi1); + } +#endif + fprintf (debug_eval_file, "\n"); + } else +#endif +#if defined FIELDBONUS || defined DROPBONUS + if ( node->score <= DONTUSE ) + printf ("%s %s %s %s DONTUSE %x\n", + mvstr[0], mvstr[1], mvstr[2], mvstr[3],node->flags); + else + printf ("%s %s %s %s score %d INC %d %x\n", + mvstr[0], mvstr[1], mvstr[2], mvstr[3],node->score,node->INCscore,node->flags); +#else + if ( node->score <= DONTUSE ) + printf ("%s %s %s %s DONTUSE %x\n", + mvstr[0], mvstr[1], mvstr[2], mvstr[3],node->flags); + else + printf ("%s %s %s %s score %d %x\n", + mvstr[0], mvstr[1], mvstr[2], mvstr[3],node->score,node->flags); +#endif + } +#endif +#else + ShowNodeCnt (cnt); +#endif +} + +void + TestPSpeed (short int (*f) (short int side), unsigned j) +{ + short i; + long cnt, rate, t1, t2; +#ifdef HASGETTIMEOFDAY +struct timeval tv; +#endif + +#ifdef HASGETTIMEOFDAY + gettimeofday(&tv,NULL); + t1 = (tv.tv_sec*100+(tv.tv_usec/10000)); +#elif defined THINK_C || defined MSDOS + t1 = clocktime(); +#else + t1 = time (0); +#endif + for (i = 0; i < j; i++) + { + (void) f (opponent); + } +#ifdef HASGETTIMEOFDAY + gettimeofday(&tv,NULL); + t2 = (tv.tv_sec*100+(tv.tv_usec/10000)); +#elif defined THINK_C || defined MSDOS + t2 = clocktime(); +#else + t2 = time (0); +#endif + cnt = j; + if (t2 - t1) + et = (t2 - t1); + else + et = 1; + rate = (et) ? ((cnt*100) / et) : 0; + /*printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);*/ +#ifdef NONDSP + printz (CP[91], cnt, rate); +#else + ShowNodeCnt (cnt); +#endif +} + + +#endif /* XSHOGI */ + + +void +SetOppTime (char *s) +{ + char *time; + char buffer[20]; + register tmp = 0; + int m, t,sec; + sec = 0; + time = &s[strlen (CP[228])]; + t = (int)strtol (time, &time, 10); + if(*time == ':'){time++; sec=(int)strtol(time, &time,10);} + m = (int)strtol (time, &time, 10); + if (t) + TimeControl.clock[opponent] = t; + if (m) + TimeControl.moves[opponent] = m; + ElapsedTime (COMPUTE_AND_INIT_MODE); +#if defined XSHOGI + /* just to inform xshogi about availability of otime command */ + printz ("otime %d %d\n", t, m); +#endif +} + + + +void +SetMachineTime (char *s) +{ + char *time; + long tmp = 0; + int m, t,sec; + time = &s[strlen (CP[197])]; + sec = 0; + t = (int)strtol (time, &time, 10); + if(*time == ':'){time++; sec=(int)strtol(time, &time,10);} + m = (int)strtol (time, &time, 10); + if (t) + TimeControl.clock[computer] = t; + if (m) + TimeControl.moves[computer] = m; + ElapsedTime (COMPUTE_AND_INIT_MODE); +#if defined XSHOGI + /* just to inform xshogi about availability of time command */ + printz ("time %d %d\n", t, m); +#endif +} + + +#if defined DEBUG || defined DEBUG_EVAL +void debug_position (FILE *D) +{ + short r, c, side, piece, l; + fprintf (D, "\n current board is\n\n"); + for (piece = pawn; piece <= king; piece++) + if (c = Captured[white][piece]) + fprintf(D, "%i%c ",c,pxx[piece]); + fprintf (D, "\n"); + for (c = 0; c < NO_COLS; c++) + fprintf (D, " %d", PawnCnt[white][c]); + fprintf (D, "\n\n"); + for (r = NO_ROWS-1; r >= 0; r--) + { char pc; + for (c = 0; c <= NO_COLS-1; c++) + { + l = locn (r, c); + pc = (is_promoted[board[l]] ? '+' : ' '); + if (color[l] == neutral) + fprintf (D, " -"); + else if (color[l] == black) + fprintf (D, "%c%c", pc, qxx[board[l]]); + else + fprintf (D, "%c%c", pc, pxx[board[l]]); + } + fprintf (D, "\n"); + } + fprintf (D, "\n"); + for (c = 0; c < NO_COLS; c++) + fprintf (D, " %d", PawnCnt[black][c]); + fprintf (D, "\n"); + for (piece = pawn; piece <= king; piece++) + if (c = Captured[black][piece]) + fprintf(D, "%i%c ",c,pxx[piece]); + fprintf (D, "\n"); +} +#endif + + + +void +InputCommand (char *command) + +/* + * Process the users command. If easy mode is OFF (the computer is thinking + * on opponents time) and the program is out of book, then make the 'hint' + * move on the board and call SelectMove() to find a response. The user + * terminates the search by entering ^C (quit siqnal) before entering a + * command. If the opponent does not make the hint move, then set Sdepth to + * zero. + */ + +{ + int eof = 0; + short have_shown_prompt = false; + short ok, done, is_move = false; + unsigned short mv; + char s[80], sx[80]; + + ok = flag.quit = done = false; + player = opponent; +#if ttblsz + if(TTadd > ttbllimit)ZeroTTable(); +#endif + if (hint > 0 && !flag.easy && !flag.force ) + { + /* A hint move for the player is available. + Compute a move for the oppnonent in background mode assuming + that the hint move will be selected by the player. */ + ft = time0; /* Save reference time for the player. */ + fflush (stdout); + algbr ((short) hint >> 8, (short) hint & 0xff, false); + strcpy (s, mvstr[0]); +#ifdef DEBUG12 + if (1) + { + FILE *D; + int r, c, l; + extern unsigned short int PrVar[]; + extern struct leaf far *root; + D = fopen ("/tmp/DEBUGA", "a+"); + fprintf (D, "score = %d\n", root->score); + fprintf (D, "inout move is %s\n", s); + for (r = 1; PrVar[r]; r++) + { + algbr (PrVar[r] >> 8, PrVar[r] & 0xff, (short) 0); + fprintf (D, " %s", mvstr[0]); + } + fclose (D); + } +#endif +#if !defined NOPOST + if (flag.post) GiveHint (); +#endif + /* do the hint move */ + if (VerifyMove (s, VERIFY_AND_TRY_MODE, &mv)) + { + +Sdepth = 0; +#ifdef QUIETBACKGROUND +#ifdef NONDSP + PromptForMove (); +#else + ShowSidetoMove (); + ShowPrompt (); +#endif + have_shown_prompt = true; +#endif /* QUIETBACKGROUND */ + /* Start computing a move until the search is interrupted. */ +#ifdef INTERRUPT_TEST + itime0 = 0; +#endif + /* would love to put null move in here */ + /* after we make the hint move make a 2 ply search with both plys our moves */ + /* think on opponents time */ + SelectMove (computer, BACKGROUND_MODE); +#ifdef INTERRUPT_TEST + ElapsedTime(COMPUTE_INTERRUPT_MODE); + if ( itime0 == 0 ) + printf("searching not terminated by interrupt!\n"); + else + printf("elapsed time from interrupt to terminating search: %ld\n",it); +#endif + /* undo the hint and carry on */ + VerifyMove (s, UNMAKE_MODE, &mv); + Sdepth = 0; + } + time0 = ft; /* Restore reference time for the player. */ + } + while (!(ok || flag.quit || done)) + { + player = opponent; +#ifdef QUIETBACKGROUND + if (!have_shown_prompt) + { +#endif /* QUIETBACKGROUND */ +#ifdef NONDSP + PromptForMove (); +#else + ShowSidetoMove (); + ShowPrompt (); +#endif +#ifdef QUIETBACKGROUND + } + have_shown_prompt = false; +#endif /* QUIETBACKGROUND */ + if ( command == NULL ) + { +#ifdef NONDSP + s[0] = sx[0] = '\0'; + while (!sx[0]) + (void) gets (sx); +#else + fflush (stdout); +#if defined MSDOS || defined THINK_C + s[0] = '\0'; + eof = ( gets (sx) == NULL ); +#else + eof = ( getstr (sx) == ERR ); +#endif +#endif + } + else + { + strcpy (sx, command); + done = true; + } + sscanf (sx, "%s", s); + if (eof) + ExitChess (); + if (s[0] == '\0') + continue; + if (strcmp (s, CP[131]) == 0) /*bd*/ + { +#if defined XSHOGI + xshogi = 0; +#endif + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); +#if defined XSHOGI + xshogi = 1; +#endif + } + else if (strcmp (s, "post") == 0) + flag.post = !flag.post; + else if (strcmp (s, CP[129]) == 0) /* noop */ ; /*alg*/ + else if ((strcmp (s, CP[180]) == 0) || (strcmp (s, CP[216]) == 0)) /* quit exit*/ + flag.quit = true; +#if !defined NOPOST + else if (strcmp (s, CP[178]) == 0) /*post*/ + { + flag.post = !flag.post; + } +#endif + else if ((strcmp (s, CP[191]) == 0) || (strcmp (s, CP[154]) == 0)) /*set edit*/ + EditBoard (); +#ifdef NONDSP + else if (strcmp (s, CP[190]) == 0) /*setup*/ + SetupBoard (); +#endif + else if (strcmp (s, CP[156]) == 0) /*first*/ + { + ok = true; + } + else if (strcmp (s, CP[162]) == 0) /*go*/ + { + ok = true; + flag.force = false; + if (computer == black) + { + computer = white; + opponent = black; + } + else + { + computer = black; + opponent = white; + } + } + else if (strcmp (s, CP[166]) == 0) /*help*/ + help (); + else if (strcmp (s, CP[221]) == 0) /*material*/ + flag.material = !flag.material; + else if (strcmp (s, CP[157]) == 0) /*force*/ +#ifdef XSHOGI + {flag.force = true; flag.bothsides = false;} +#else + {flag.force = !flag.force; flag.bothsides = false;} +#endif + else if (strcmp (s, CP[134]) == 0) /*book*/ + Book = Book ? 0 : BOOKFAIL; + else if (strcmp (s, CP[172]) == 0) /*new*/ + { + NewGame (); + UpdateDisplay (0, 0, 1, 0); + } + else if (strcmp (s, CP[171]) == 0) /*list*/ + ListGame (); + else if (strcmp (s, CP[169]) == 0 || strcmp (s, CP[217]) == 0) /*level clock*/ + SelectLevel (sx); + else if (strcmp (s, CP[165]) == 0) /*hash*/ + flag.hash = !flag.hash; + else if (strcmp (s, CP[227]) == 0) /*gamein*/ + flag.gamein = !flag.gamein; + else if (strcmp (s, CP[226]) == 0) /*beep*/ + flag.beep = !flag.beep; + else if (strcmp (s, CP[197]) == 0) /*time*/ + { SetMachineTime (sx); } + else if (strcmp (s, CP[228]) == 0) /*otime*/ + { SetOppTime (sx); } + else if (strcmp (s, CP[33]) == 0) /*Awindow*/ + ChangeAlphaWindow (); + else if (strcmp (s, CP[39]) == 0) /*Bwindow*/ + ChangeBetaWindow (); + else if (strcmp (s, CP[183]) == 0) /*rcptr*/ + flag.rcptr = !flag.rcptr; + else if (strcmp (s, CP[168]) == 0) /*hint*/ + GiveHint (); + else if (strcmp (s, CP[135]) == 0) /*both*/ + { + flag.bothsides = !flag.bothsides; + flag.force = false; + Sdepth = 0; + ElapsedTime (COMPUTE_AND_INIT_MODE); + SelectMove (opponent, FOREGROUND_MODE); + ok = true; + } + else if (strcmp (s, CP[185]) == 0) /*reverse*/ + { + flag.reverse = !flag.reverse; + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); + } + else if (strcmp (s, CP[195]) == 0) /*switch*/ + { + computer = computer ^ 1; + opponent = opponent ^ 1; + xwndw = (computer == black) ? WXWNDW : BXWNDW; + flag.force = false; + Sdepth = 0; + ok = true; + } + else if (strcmp (s, CP[203]) == 0) /*black*/ + { + computer = white; + opponent = black; + xwndw = WXWNDW; + flag.force = false; + Sdepth = 0; + + /* + * ok = true; don't automatically start with black command + */ + } + else if (strcmp (s, CP[133]) == 0) /*white*/ + { + computer = black; + opponent = white; + xwndw = BXWNDW; + flag.force = false; + Sdepth = 0; + + /* + * ok = true; don't automatically start with white command + */ + } + else if (strcmp (s, CP[201]) == 0 && GameCnt > 0) /*undo*/ + { + Undo (); + } + else if (strcmp (s, CP[184]) == 0 && GameCnt > 1) /*remove*/ + { + Undo (); + Undo (); + } +#if !defined XSHOGI + else if (strcmp (s, CP[207]) == 0) /*xget*/ + GetXGame (); + else if (strcmp (s, "xsave") == 0) /*xsave*/ + SaveXGame (); + else if (strcmp (s, "bsave") == 0) /*bsave*/ + BookSave (); +#endif +#ifdef EASY_OPENINGS + else if (strcmp (s, "?") == 0 || strcmp (s, "!") == 0 || strcmp (s, "~") == 0) +#else + else if (strcmp (s, "?") == 0 || strcmp (s, "!") == 0) +#endif + FlagMove (*s); + else if (strcmp (s, CP[160]) == 0) /*get*/ + GetGame (); + else if (strcmp (s, CP[189]) == 0) /*save*/ + SaveGame (); + else if (strcmp (s, CP[151]) == 0) /*depth*/ + ChangeSearchDepth (); +#ifdef DEBUG + else if (strcmp (s, CP[147]) == 0) /*debuglevel*/ + ChangeDbLev (); +#endif /* DEBUG */ + else if (strcmp (s, CP[164]) == 0) /*hashdepth*/ + ChangeHashDepth (); + else if (strcmp (s, CP[182]) == 0) /*random*/ + dither = DITHER; + else if (strcmp (s, CP[229]) == 0) /*hard*/ + flag.easy = false; + else if (strcmp (s, CP[152]) == 0) /*easy*/ + flag.easy = !flag.easy; + else if (strcmp (s, CP[230]) == 0) /*tsume*/ + flag.tsume = !flag.tsume; + else if (strcmp (s, CP[143]) == 0) /*contempt*/ + SetContempt (); + else if (strcmp (s, CP[209]) == 0) /*xwndw*/ + ChangeXwindow (); + else if (strcmp (s, CP[186]) == 0) /*rv*/ + { + flag.rv = !flag.rv; + UpdateDisplay (0, 0, 1, 0); + } + else if (strcmp (s, CP[145]) == 0) /*coords*/ + { + flag.coords = !flag.coords; + UpdateDisplay (0, 0, 1, 0); + } + else if (strcmp (s, CP[193]) == 0) /*stars*/ + { + flag.stars = !flag.stars; + UpdateDisplay (0, 0, 1, 0); + } +#if !defined XSHOGI + else if (strcmp (s, CP[5]) == 0) /*moves*/ + { short temp; +#ifdef DEBUG_EVAL + debug_eval = ((debug_eval_file = fopen(EVALFILE,"w")) != NULL); +#endif +#if MAXDEPTH > 3 + if ( GameCnt > 0 ) { + extern unsigned short int PrVar[MAXDEPTH]; + SwagHt = (GameList[GameCnt].gmove == PrVar[1]) ? PrVar[2] : 0; + } else +#endif + SwagHt = 0; + ShowMessage (CP[108]); /*test movelist*/ + temp = generate_move_flags; + generate_move_flags = true; + TestSpeed (MoveList, 1); + generate_move_flags = temp; + ShowMessage (CP[107]); /*test capturelist*/ + TestSpeed (CaptureList, 1); + ShowMessage (CP[85]); /*test score position*/ + ExaminePosition(opponent); + TestPSpeed (ScorePosition, 1); +#ifdef DEBUG_EVAL + if ( debug_eval ) fclose(debug_eval_file); + debug_eval = false; +#endif + } + else if (strcmp (s, CP[196]) == 0) /*test*/ + { +#ifdef SLOW_CPU + ShowMessage (CP[108]);/*test movelist*/ + TestSpeed (MoveList, 2000); + ShowMessage (CP[107]);/*test capturelist*/ + TestSpeed (CaptureList, 3000); + ShowMessage (CP[85]);/*test score position*/ + ExaminePosition(opponent); + TestPSpeed (ScorePosition, 1500); +#else + ShowMessage (CP[108]);/*test movelist*/ + TestSpeed (MoveList, 20000); + ShowMessage (CP[107]);/*test capturelist*/ + TestSpeed (CaptureList, 30000); + ShowMessage (CP[85]);/*test score position*/ + ExaminePosition(opponent); + TestPSpeed (ScorePosition, 15000); +#endif + } +#ifdef DEBUG_EVAL + else if (strcmp (s, "eval") == 0) /*eval*/ + { + debug_eval = true; + if ( debug_eval_file = fopen(EVALFILE,"w") ) { + InitializeStats(); + ExaminePosition(opponent); + fprintf (debug_eval_file, "\nscoring for %s to move...\n\n", + ColorStr[player]); + ScorePosition (player); + fclose (debug_eval_file); + } + debug_eval = false; + } + else if (strcmp (s, "debug_eval") == 0) /*debug_eval*/ + { + if ( debug_eval ) + { + fclose (debug_eval_file); + debug_eval = false; + } + else + { + debug_eval_file = fopen(EVALFILE,"w"); + debug_eval = (debug_eval_file != NULL); + } + } + else if (strcmp (s, "pattern") == 0) /*pattern*/ + { + debug_eval = true; + if ( debug_eval_file = fopen(EVALFILE,"w") ) { + short side; + for (side=black; side<=white; side++) { + short s = ScorePatternDistance (side); + fprintf (debug_eval_file, "\npattern distance score for %s is %d\n\n", + ColorStr[side], s); + } + fclose (debug_eval_file); + } + debug_eval = false; + } +#endif /* DEBUG_EVAL */ + else + if (strcmp (s, CP[179]) == 0) /*p*/ + ShowPostnValues (); + else if (strcmp (s, CP[148]) == 0) /*debug*/ + DoDebug (); +#endif /* XSHOGI */ + else + { + if ( flag.mate ) + ok = true; + else if ( ok = VerifyMove (s, VERIFY_AND_MAKE_MODE, &mv) ) + { + /* check for repetition */ + short int rpt = repetition(); + if ( rpt >= 3 ) + { DRAW = CP[101]; + ShowMessage(DRAW); + GameList[GameCnt].flags |= draw; + flag.mate = true; + } + else + is_move = true; + } + Sdepth = 0; + } + } + + ElapsedTime (COMPUTE_AND_INIT_MODE); + + if (flag.force) + { + computer = opponent; + opponent = computer ^ 1; + } +#if defined XSHOGI + /* add remaining time in milliseconds for xshogi */ + if ( is_move ) + printz ("%d. %s %ld\n", ++mycnt2, s, TimeControl.clock[player]*10); +#ifdef notdef /* optional pass best line to frontend with move */ +#if !defined NOPOST + if (flag.post && !flag.mate) + { + register int i; + + printz (" %6d ", MSCORE); + for (i = 1; MV[i] > 0; i++) + { + algbr ((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false); + printz ("%5s ", mvstr[0]); + } + } +#endif + printz ("\n"); +#endif +#endif /* XSHOGI */ + signal (SIGINT, TerminateSearch); +#if !defined MSDOS && !defined THINK_C && !defined BORLAND_CPP + signal (SIGQUIT, TerminateSearch); +#endif /* MSDOS */ + +} + + +#if defined NOFIONREAD +#ifdef FIONREAD +#undef FIONREAD +#endif +#endif + + + + +#ifdef HASGETTIMEOFDAY +void +ElapsedTime (ElapsedTime_mode iop) + + +/* + * Determine the time that has passed since the search was started. If the + * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout + * to true which will terminate the search. + * iop = COMPUTE_MODE calculate et, bump ETnodes + * iop = COMPUTE_AND_INIT_MODE calculate et, set timeout if time exceeded, + * set reference time + */ + +{ + struct timeval tv; + long current_time; +#if !defined MSDOS + int nchar; + extern int errno; + int i; +#ifdef FIONREAD + if (i = ioctl ((int) 0, FIONREAD, &nchar)) + { + perror ("FIONREAD"); + fprintf (stderr, + "You probably have a non-ANSI ; see README. %d %d %x\n", + i, errno, FIONREAD); + exit (1); + } + + if (nchar) + { + if (!flag.timeout) + flag.back = true; + flag.bothsides = false; + } +#endif /*FIONREAD*/ +#else + if (kbhit ()) + { + if (!flag.timeout) + flag.back = true; + flag.bothsides = false; + } +#endif /* MSDOS */ + gettimeofday(&tv,NULL); + current_time = tv.tv_sec*100 + (tv.tv_usec/10000); +#ifdef INTERRUPT_TEST + if ( iop == INIT_INTERRUPT_MODE ) + { + itime0 = current_time; + } + else if ( iop == COMPUTE_INTERRUPT_MODE ) + { + it = current_time - itime0; + } + else +#endif + { + et = current_time - time0; + ETnodes = NodeCnt + znodes; + if (et < 0) + { +#ifdef INTERRUPT_TEST + printf("elapsed time %ld not positive\n", et); +#endif + et = 0; + } + if (iop == COMPUTE_AND_INIT_MODE) + { + if (et > ResponseTime + ExtraTime && Sdepth > MINDEPTH) + flag.timeout = true; + time0 = current_time; + } +#if !defined NONDSP +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + UpdateClocks (); +#endif + } +} + +#else + +void +ElapsedTime (ElapsedTime_mode iop) + + +/* + * Determine the time that has passed since the search was started. If the + * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout + * to true which will terminate the search. iop = 0 calculate et bump ETnodes + * iop = 1 calculate et set timeout if time exceeded, calculate et + */ + +{ + long current_time; +#if !defined MSDOS + int nchar; + extern int errno; + int i; +#ifdef FIONREAD + if (i = ioctl ((int) 0, FIONREAD, &nchar)) + { + perror ("FIONREAD"); + fprintf (stderr, + "You probably have a non-ANSI ; see README. %d %d %x\n", + i, errno, FIONREAD); + exit (1); + } + + if (nchar) + { + if (!flag.timeout) + flag.back = true; + flag.bothsides = false; + } +#endif /*FIONREAD*/ +#else + if (kbhit ()) + { + if (!flag.timeout) + flag.back = true; + flag.bothsides = false; + } +#endif /* MSDOS */ +#if defined THINK_C || defined MSDOS + et = ((current_time = clocktime()) - time0); +#else + et = ((current_time = time ((long *) 0)) - time0) * 100; +#endif +#ifdef INTERRUPT_TEST + if ( iop == INIT_INTERRUPT_MODE ) + { + itime0 = current_time; + } + else if ( iop == COMPUTE_INTERRUPT_MODE ) + { + it = current_time - itime0; + } + else +#endif + { + ETnodes = NodeCnt + znodes; + if (et < 0) + { +#ifdef INTERRUPT_TEST + printf("elapsed time %ld not positive\n", et); +#endif + et = 0; + } + if (iop == COMPUTE_AND_INIT_MODE) + { + if (et > ResponseTime + ExtraTime && Sdepth > MINDEPTH) + flag.timeout = true; + time0 = current_time; + } +#if !defined NONDSP +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + UpdateClocks (); +#endif + } +} +#endif +void +SetTimeControl (void) +{ + if (TCflag) + { + TimeControl.moves[black] = TimeControl.moves[white] = TCmoves; + TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100; + TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100; + } + else + { + TimeControl.moves[black] = TimeControl.moves[white] = 0; + TimeControl.clock[black] = TimeControl.clock[white] = 0; + } + flag.onemove = (TCmoves == 1); + et = 0; + ElapsedTime (COMPUTE_AND_INIT_MODE); +} + +#if defined XSHOGI +void +TerminateChess (int sig) +{ + ExitChess (); +} + +#endif + + + + diff --git a/src/eval.c b/src/eval.c new file mode 100644 index 0000000..7d6a176 --- /dev/null +++ b/src/eval.c @@ -0,0 +1,3128 @@ +/* + * eval.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" + +#include "pattern.h" + + +/* Hash table for preventing multiple scoring of the same position */ + +int EADD = 0; /* number of writes to the cache table */ +int EGET = 0; /* number of hits to the cache table */ +int PUTVAR = false; /* shall the current scoring be cached? */ + + +/* Pieces and colors of initial board setup */ + +const small_short Stboard[NO_SQUARES] = +{lance,knight,silver,gold,king,gold,silver,knight,lance, + 0, bishop, 0, 0, 0, 0, 0, rook, 0, + pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, + 0, rook, 0, 0, 0, 0, 0, bishop, 0, + lance,knight,silver,gold,king,gold,silver,knight,lance}; + + +const small_short Stcolor[NO_SQUARES] = +{black, black, black, black, black, black, black, black, black, + neutral, black, neutral, neutral, neutral, neutral, neutral, black, neutral, + black, black, black, black, black, black, black, black, black, + neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, + neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, + neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, + white, white, white, white, white, white, white, white, white, + neutral, white, neutral, neutral, neutral, neutral, neutral, white, neutral, + white, white, white, white, white, white, white, white, white}; + + +/* Actual pieces and colors */ + +small_short board[NO_SQUARES], color[NO_SQUARES]; + + +/* relative piece values at the beginning of main stages */ + +#define MAIN_STAGES 4 + +static small_short ispvalue[NO_PIECES][MAIN_STAGES] = + { 0, 35, 70, 99, /* main stage borders */ + /* ------------------- */ + 7, 7, 8, 10, /* Pawn */ + 20, 35, 45, 60, /* Lance */ + 20, 35, 45, 60, /* Knight */ + 35, 40, 60, 80, /* Silver */ + 35, 50, 65, 80, /* Gold */ + 90, 90, 90, 90, /* Bishop */ + 95, 95, 95, 95, /* Rook */ + 15, 25, 40, 65, /* promoted Pawn */ + 25, 45, 55, 65, /* promoted Lance */ + 25, 45, 55, 65, /* promoted Knight */ + 35, 55, 75, 75, /* promoted Silver */ + 99, 99, 99, 99, /* promoted Bishop */ + 97, 97, 99, 99, /* promoted Rook */ + 100, 100, 100, 100, /* King */ + }; + +/* Features and Weights */ + +#define ATAKD 0 +#define HUNGP 1 +#define HUNGX 2 +#define CNTRL5TH 3 +#define HOLES 4 +#define PCASTLE 5 +#define PATTACK 6 +#define CTRLK 7 +#define PROTECT 8 +#define HCLSD 9 +#define PINVAL 10 +#define XRAY 11 +#define OPENWRONG 12 +#define SEED 13 +#define LOOSE 14 +#define MOBILITY 15 +#define TARGET 16 +#define KSFTY 17 +#define HOPN 18 +#define PROMD 19 +#define KINGOD 20 +#define PWNDROP 21 +#define DFFDROP 22 +#define FCLATTACK 23 +#define KNGATTACK 24 +#define KNGPROTECT 25 +#define DNGLPC 26 +#define LSATTACK 27 +#define NIHATTACK 28 +#define COHESION 29 +#define OPPDROP 30 + +static small_short weight[NO_FEATURES+1][MAIN_STAGES+2] = + { 80, 100, 100, 40, 10, 15, /* ATAKD */ + 80, 100, 100, 50, 14, 10, /* HUNGP */ + 80, 100, 100, 50, 18, 12, /* HUNGX */ + 100, 50, 0, 0, 2, 1, /* CNTRL5TH */ + 100, 100, 60, 10, 4, 2, /* HOLES */ + 100, 50, 0, 0, 14, 7, /* PCASTLE */ + 100, 50, 0, 0, 6, 12, /* PATTACK */ + 10, 40, 70, 100, 10, 15, /* CTRLK */ + 100, 80, 50, 40, 2, 1, /* PROTECT */ + 40, 100, 40, 5, 4, 4, /* HCLSD */ + 80, 100, 80, 30, 10, 15, /* PINVAL */ + 80, 100, 60, 15, 6, 10, /* XRAY */ + 100, 50, 0, 0, 15, 15, /* OPENWRONG */ + 0, 40, 70, 100, 8, 12, /* SEED */ + 50, 100, 80, 20, 5, 3, /* LOOSE */ + 50, 100, 80, 50,100,100, /* MOBILITY (%) */ + 50, 100, 80, 50, 4, 8, /* TARGET */ + 50, 40, 100, 80, 8, 4, /* KSFTY */ + 80, 100, 60, 20, 5, 5, /* HOPN */ + 20, 40, 80, 100, 3, 6, /* PROMD */ + 20, 40, 80, 100, 4, 1, /* KINGOD */ + 5, 40, 100, 50, 0, 4, /* PWNDROP */ + 0, 20, 80, 100, 0, 4, /* DFFDROP */ + 20, 50, 100, 80, 0, 4, /* FCLATTACK */ + 0, 20, 80, 100, 0, 8, /* KNGATTACK */ + 40, 80, 100, 80, 6, 0, /* KNGPROTECT */ + 50, 100, 60, 10, 0, 8, /* DNGPC */ + 30, 100, 60, 5, 0, 6, /* LSATTACK */ + 0, 50, 80, 100, 0, 8, /* NIHATTACK */ + 50, 100, 80, 60, 8, 0, /* COHESION */ + 100, 100, 80, 60, 4, 4, /* OPPDROP */ + }; +short ADVNCM[NO_PIECES]; + +/* distance to enemy king */ +static const EnemyKingDistanceBonus[10] = +{0, 6, 4, -1, -3, -4, -6, -8, -10, -12}; + +/* distance to own king */ +static const OwnKingDistanceBonus[10] = +{0, 5, 2, 1, 0, -1, -2, -3, -4, -5}; + +/* distance to promotion zone */ +static const PromotionZoneDistanceBonus[NO_ROWS] = +{0, 0, 0, 0, 2, 6, 6, 8, 8}; + +#define MAX_BMBLTY 20 +#define MAX_RMBLTY 20 +#define MAX_LMBLTY 8 + +/* Bishop mobility bonus indexed by # reachable squares */ +static const short BMBLTY[MAX_BMBLTY] = + {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16}; + +/* Rook mobility bonus indexed by # reachable squares */ +static const short RMBLTY[MAX_RMBLTY] = + {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16}; + +/* Lance mobility bonus indexed by # reachable squares */ +static const short LMBLTY[MAX_LMBLTY] = + {0, 0, 0, 0, 4, 6, 8, 10}; + +static const short MBLTY[NO_PIECES] = + {0, 2, 1, 10, 5, 5, 1, 1, 5, 5, 5, 5, 1, 1, 4}; + +static const short KTHRT[36] = +{0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80}; + +static small_short fvalue[2][NO_FEATURES]; + +long int atak[2][NO_SQUARES]; /* threats to squares */ +small_short sseed[NO_SQUARES]; /* square occupied by a seed piece? */ + +struct signature threats_signature[2] = /* statistics valid for position ... */ + {-1, -1, -1, -1}; /* atak and sseed available */ + +small_short starget[2][NO_SQUARES]; /* significance as a target for a side of a square */ +small_short sloose[NO_SQUARES]; /* square occupied by a loose piece? */ +small_short shole[NO_SQUARES]; /* empty square a hole? */ +small_short shung[NO_SQUARES]; /* hung piece? */ + +struct signature squares_signature = /* statistics valid for position ... */ + {0, 0}; /* starget, sloose, shole, shung available */ + +short target[2], seed[2], loose[2], hole[2]; + +short captured[2]; /* number of captured pieces */ +short dcaptured[2]; /* different types of captured pieces */ + +small_short Kdist[2][NO_SQUARES]; /* distance to king */ + +short MAXADIST, MAXCDIST; /* maximum half move distance to pattern */ + +char GameType[2] = {UNKNOWN,UNKNOWN}; /* choosen game type of each side */ + + +static short attack_opening_sequence[2]; /* current castle patterns */ +static short castle_opening_sequence[2]; /* current attack formations */ + +static small_short Mpawn[2][NO_SQUARES]; +static small_short Msilver[2][NO_SQUARES]; +static small_short Mgold[2][NO_SQUARES]; +static small_short Mking[2][NO_SQUARES]; +static small_short Mlance[2][NO_SQUARES]; +static small_short Mknight[2][NO_SQUARES]; +static small_short Mbishop[2][NO_SQUARES]; +static small_short Mrook[2][NO_SQUARES]; + +static Mpiece_array Mpawn, Mlance, Mknight, Msilver, Mgold, + Mbishop, Mrook, Mking; + +Mpiece_array *Mpiece[NO_PIECES] = + { NULL, &Mpawn, &Mlance, &Mknight, &Msilver, &Mgold, &Mbishop, &Mrook, + &Mgold, &Mgold, &Mgold, &Mgold, &Mbishop, &Mrook, &Mking }; + + +static short c1, c2; + +static small_short *PC1, *PC2; + +static small_short *fv1; + +static long *atk1, *atk2; + +static long a1, a2; + + +#define csquare(side,sq) ((side==black)?sq:(NO_SQUARES_1-sq)) +#define crow(side,sq) row(csquare(side,sq)) +#define ccolumn(side,sq) column(csquare(side,sq)) + +inline static short on_csquare(short side,short piece,short square) +{ short sq; + return(board[sq=csquare(side,square)]==piece && color[sq]==side); +} + +inline static short on_column(short side,short piece,short c) +{ short sq; + for (sq = c; sq < NO_SQUARES; sq+=9) + if (on_csquare(side,piece,sq)) + return(true); + return(false); +} + +#define empty_csquare(side,square)\ + (board[csquare(side,square)]==no_piece) + +inline static short on_left_side(short side,short piece) +{ short c; + for (c=0; c<4; c++) + if (on_column(side,piece,c)) + return(true); + return(false); +} + +inline static short on_right_side(short side,short piece) +{ short c; + for (c=5; c= 0; r--) + { + for (c = 0; c < NO_COLS; c++) + { + short sq = (r * NO_COLS) + c; + fprintf(D,"%5d",svalue[sq]); + } + fprintf (D, "\n"); + } + fprintf (D, "\n"); +} + +#endif + + +void +debug_table (FILE *D, small_short *table, char *s) +{ + short r, c; + + fprintf (D, "\n%s\n", s); + for (r = (NO_ROWS-1); r >= 0; r--) + { + for (c = 0; c < NO_COLS; c++) + { + short sq = (r * NO_COLS) + c; + fprintf(D,"%5d",table[sq]); + } + fprintf (D, "\n"); + } + fprintf (D, "\n"); +} + + +#endif + + +void +threats (short int side) +/* + * Fill array atak[side][] with info about ataks to a square. Bits 16-31 are set + * if the piece (king..pawn) ataks the square. Bits 0-15 contain a count of + * total ataks to the square. + * Fill array sseed[] with info about occupation by a seed piece. + */ +{ + register short u, sq; + long int c; + long int *a; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char far *ppos, *pdir; +#endif + short i, kd, piece, xside; + small_short *PL; + + if ( MatchSignature(threats_signature[side]) ) { + /* data valid for current positional signature */ + return; + } + + a = atak[side]; + xside = side ^ 1; + + array_zero (a, NO_SQUARES * sizeof(a[0])); + + PL = PieceList[side]; + for (i = PieceCnt[side]; i >= 0; i--) + { short ptyp; + sq = PL[i]; + piece = board[sq]; + ptyp = ptype[side][piece]; + c = control[piece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + do { + a[u] = ((a[u]+1) | c); + if ( (kd = Kdist[xside][u]) < 2 ) { + sseed[sq] += 2 - kd; + seed[side]++; + } +#ifdef SAVE_NEXTPOS + u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u) + : next_direction(ptyp,&d,sq)); +#else + u = ((color[u] == neutral) ? ppos[u] : pdir[u]); +#endif + } while (u != sq); + } + + /* data valid for current positional signature */ + CopySignature(threats_signature[side]); +} + + +/* + * Compute the board square with nunmap offset "id". + * If side==white, offset is negated. + * inunmap[sq] is the corresponding nunmap index isq. + * nunmap[isq+id] computes the board square. If negative, + * it is outside the board. + */ + +static void add_target (short sq, short side, short id) +{ + short isq,tsq,xside; + isq = inunmap[sq]; + tsq = (side == black) ? nunmap[isq+id] : nunmap[isq-id]; + if ( tsq >= 0 ) { + target[xside = side^1]++; + if ( atak[side][tsq] ) + starget[xside][tsq]++; /* protected target square */ + else + starget[xside][tsq]+=2; /* unprotected target square */ + } +} + + +/* + * Target squares can be vertically ahead, diagonally ahead + * or diagonally behind. + */ + +static void CheckTargetPiece (short sq, short side) +{ + switch ( board[sq] ) { + case pawn: /* vertically ahead if unprotected */ + if ( !atak[side][sq] ) + add_target(sq,side,11); + break; + case king: /* diagonally and vertically ahead */ + add_target(sq,side,10); + add_target(sq,side,11); + add_target(sq,side,12); + break; + case rook: /* diagonally ahead and behind */ + add_target(sq,side,10); + add_target(sq,side,12); + add_target(sq,side,-10); + add_target(sq,side,-12); + break; + case bishop: /* vertically ahead */ + add_target(sq,side,11); + break; + case knight: /* vertically ahead if advanced */ + if ( sq != 1 && sq != 7 && sq != 73 && sq != 79 ) + add_target(sq,side,11); + break; + } +} + + + +static +ScoreKingOpeningFeatures (void) +{ + short s = 0, sq = OwnKing, ds; + + if ( GameType[c1] == STATIC_ROOK ) { + /* Malus for king on right side or fifth file */ + short c; + c = 4 - ccolumn(c1,sq); + if ( c < 0 || (c == 0 && sq != kingP[c1]) ) { + s += (ds = -c - c - fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for king on right side (Static)\n",ds); +#endif + } + } else if ( GameType[c1] == RANGING_ROOK ) { + /* Malus for king on left side or fifth file */ + short c; + c = 4 - ccolumn(c1,sq); + if ( c > 0 || (c == 0 && sq != kingP[c1]) ) { + s += (ds = -c - c - fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for king on left side (Ranging)\n",ds); +#endif + } + /* Malus for king moved before rook switch */ + if ( sq != kingP[c1] ) { + if ( on_csquare(c1,rook,16) ) { + s += (ds = -4 * fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for king moved before rook switch (Ranging)\n",ds); +#endif + } + } else { + /* Malus for sitting king after rook switch */ + if ( !on_csquare(c1,rook,16) ) { + s += (ds = -2 * fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for sitting king after rook switch (Ranging)\n",ds); +#endif + } + } + /* Malus for defending general moved before king switch to right side */ + if ( ccolumn(c1,sq) < 6 ) { + if ( Mvboard[csquare(c1,5)] || Mvboard[csquare(c1,6)] ) { + s += (ds = -2 * fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for defending general moved before king switch (Ranging)\n",ds); +#endif + } + } + } + return s; +} + + +inline +static +ExamineSquares (void) + +{ + register short sq, side, piece, n; + + if ( MatchSignature(squares_signature) ) { + /* data valid for current positional signature */ + return; + } + + array_zero(shole,sizeof(shole)); + array_zero(sloose,sizeof(sloose)); + array_zero(starget,sizeof(starget)); + + hole[0] = hole[1] = loose[0] = loose[1] = target[0] = target[1] = 0; + + for ( sq = 0; sq < NO_SQUARES; sq++ ) + { + if ( (side = color[sq]) == neutral ) + { + if ( InWhiteCamp(sq) ) { + if ( !atak[white][sq] ) { + shole[sq] = 1; + hole[white]++; + } + } else if ( InBlackCamp(sq) ) { + if ( !atak[black][sq] ) { + shole[sq] = 1; + hole[black]++; + } + } + } + else + { /* occupied by "side" piece */ + if ( !atak[side][sq] ) { + sloose[sq] = 1; + loose[side]++; + } + CheckTargetPiece(sq,side); + } + } + +#ifdef DEBUG_EVAL + if ( debug_eval ) { + char buffer[80]; + debug_position (debug_eval_file); + debug_ataks (debug_eval_file, atak[black]); + debug_ataks (debug_eval_file, atak[white]); + sprintf(buffer,"%d Black and %d White SEED PIECES",seed[black],seed[white]); + debug_table (debug_eval_file,sseed,buffer); + sprintf(buffer,"%d Black TARGETS",target[black]); + debug_table (debug_eval_file,starget[black],buffer); + sprintf(buffer,"%d White TARGETS",target[white]); + debug_table (debug_eval_file,starget[white],buffer); + sprintf(buffer,"%d Black and %d White LOOSE PIECES",loose[black],loose[white]); + debug_table (debug_eval_file,sloose,buffer); + sprintf(buffer,"%d Black and %d White HOLES",hole[black], hole[white]); + debug_table (debug_eval_file,shole,buffer); + } +#endif + + for ( side=black; side<=white; side++ ) { + captured[side] = dcaptured[side] = 0; + for ( piece = pawn; piece <= rook; piece++ ) { + if ( (n = Captured[side][piece]) != 0 ) { + if ( piece != pawn ) + captured[side] += n; + dcaptured[side]++; + } + } +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%s captured=%d dcaptured=%d\n", + ColorStr[side],captured[side], dcaptured[side]); + } +#endif + } + + /* Data valid for current positional signature */ + CopySignature(squares_signature); +} + + + +/* ............ POSITIONAL EVALUATION ROUTINES ............ */ + +/* + * Inputs are: + * mtl[side] - value of all material + * hung[side] - count of hung pieces + * Tscore[ply] - search tree score for ply ply + * Pscore[ply] - positional score for ply ply + * INCscore - bonus score or penalty for certain moves + * Sdepth - search goal depth + * xwndw - evaluation window about alpha/beta + * EWNDW - second evaluation window about alpha/beta + * ChkFlag[ply]- checking piece at level ply or 0 if no check + * TesujiFlag[ply]- 1 if tesuji move at level ply or 0 if no tesuji + * PC1[column] - # of my pawns in this column + * PC2[column] - # of opponents pawns in column + * PieceCnt[side] - just what it says + */ + + + +int +evaluate (register short int side, + register short int ply, + register short int alpha, + register short int beta, + short int INCscore, + short int *InChk, /* output Check flag */ + short int *blockable) /* king threat blockable */ + +/* + * Compute an estimate of the score by adding the positional score from the + * previous ply to the material difference. If this score falls inside a + * window which is 180 points wider than the alpha-beta window (or within a + * 50 point window during quiescence search) call ScorePosition() to + * determine a score, otherwise return the estimated score. + * "side" has to moved. + */ + +{ + register short evflag, xside; + short s, sq; + + xside = side ^ 1; + s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */; + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf (debug_eval_file, "estimated score at ply %d:%d, -%d+%d-%d-%d\n", + ply, s, Pscore[ply-1], mtl[side], mtl[xside], INCscore ); +#endif + + hung[black] = hung[white] = 0; + + /* should we use the estimete or score the position */ + if ( (ply == 1) || + (ply == Sdepth) || + (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30)) +#ifdef CACHE + || (use_etable && CheckEETable (side)) +#endif + ) + { short sq; + /* score the position */ +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf (debug_eval_file, "do NOT use the estimete\n"); +#endif + array_zero (sseed, sizeof(sseed)); + + seed[0] = seed[1] = 0; + threats (side); + if (Anyatak (side, sq=PieceList[xside][0]) && board[sq] == king) { + *InChk = (board[sq=PieceList[side][0]] == king) ? SqAtakd (sq, xside, blockable) : false; + return ((SCORE_LIMIT+1001) - ply); + } + threats (xside); + *InChk = (board[sq=PieceList[side][0]] == king) ? Anyatak (xside, sq) : false; + *blockable = true; +#ifndef BAREBONES + EvalNodes++; +#endif + if ( ply > 4 ) + PUTVAR=true; + ExamineSquares(); + s = ScorePosition (side); + PUTVAR = false; + } + else + { + /* use the estimate but look at check */ + short sq; +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf (debug_eval_file, "use the estimete\n"); +#endif + *InChk = (board[sq=PieceList[side][0]] == king) ? SqAtakd (sq, xside, blockable) : false; + if ( board[sq=PieceList[xside][0]] == king && SqAtakd (sq, side, blockable) ) { + return ((SCORE_LIMIT+1001) - ply); + } + } + + Pscore[ply] = s - mtl[side] + mtl[xside]; + ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0); + return (s); +} + + +static short value_of_weakest_attacker (long a2) +{ + register short piece; + short min_value, v; + min_value = SCORE_LIMIT; + for ( piece = pawn; piece <= king; piece++ ) + if ( control[piece] & a2 ) + { + if ( min_value > (v = (*value)[stage][piece]) ) + min_value = v; + } + return min_value; +} + + +inline +int +BRLscan (register short int sq, short int *mob) + +/* + * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, XRAY attacks, and pins. + * Let BRL be the bishop, rook, or lance. + * Let P be the first piece (no king and no pawn) in a direction and let Q be the second + * piece in the same direction. If Q is an unprotected opponent's piece with + * bigger relative value than BRL, there is a pin if P is an opponent's piece and + * there is an XRAY attack if P is an own piece. + * Increment the hung[] array if a pin is found. + */ +{ +#ifdef SAVE_NEXTPOS + short d, dd; +#else + register unsigned char far *ppos, *pdir; +#endif + register short s, mobx; + register short u, xu, pin, ptyp, csq = column(sq); + short piece, upiece, xupiece, rvalue, ds; + small_short *Kd = Kdist[c2]; + mobx = s = 0; + piece = board[sq]; + + rvalue = (*value)[stage][piece]; + ptyp = ptype[c1][upiece = unpromoted[piece]]; + rvalue = (*value)[stage][upiece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + pin = -1; /* start new direction */ + do + { + if ( Kd[u] < 2 ) { + s += (ds = fv1[CTRLK] * (2-Kd[u])); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for threatening square %d away from enemy king\n", + ds, Kd[u]); +#endif + } + if ( (ds = starget[c1][u]) != 0 ) { + /* threatening a target square */ + if ( pin < 0 || /* direct threat */ + color[pin] == c2 ) /* pin threat */ { + s += (ds *= fv1[TARGET]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for threatening target square\n",ds); +#endif + } + } + if ( (ds = shole[u]) != 0 ) { + /* attacking or protecting a hole */ + s += (ds = fv1[HOLES]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for threatening a hole\n",ds); +#endif + } else if ( InPromotionZone(c1,u) ) { + /* attacking a square in promotion zone */ + s += (ds = fv1[HOLES] / 2); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for threatening promotion zone\n",ds); +#endif + } + if (color[u] == neutral) + { +#ifdef SAVE_NEXTPOS + dd = d; + xu = next_position(ptyp,&d,sq,u); + if ( xu == next_direction(ptyp,&dd,sq) ) + pin = -1; /* oops new direction */ +#else + if ((xu = ppos[u]) == pdir[u]) + pin = -1; /* oops new direction */ +#endif + u = xu; + mobx++; + } + else + { /* there is a piece in current direction */ + if (pin < 0) + { /* it's the first piece in the current direction */ +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file, + "first piece on square %d is an %s piece\n", + u, (color[u]==c1) ? "own" : "enemy"); +#endif + if ( color[u] == c1 ) { + /* own intercepting piece in xray attack */ + if ( upiece == lance ) { + /* lance xray */ + if ( board[u] == pawn ) { + s += (ds = 2*fv1[PROTECT]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance protecting pawn\n",ds); +#endif + } else if ( in_opening_stage ) { + s += (ds = -2*fv1[PROTECT]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance protecting non-pawn\n",ds); +#endif + } + } else { + /* bishop or rook xray */ + if ( upiece == bishop && board[u] == pawn && GameType[c1] == STATIC_ROOK ) { + s += (ds = -2*fv1[HCLSD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for own pawn in bishops direction\n",ds); +#endif + } else if ( upiece == rook && board[u] == lance && GameType[c1] == STATIC_ROOK && column(u) == csq) { + s += (ds = fv1[XRAY]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance supported by rook\n",ds); +#endif + } + } + } else { + /* enemy's intercepting piece in pin attack */ + if ( upiece == lance ) { + /* lance pin attack */ + if ( board[u] == pawn ) { + s += (ds = -2*fv1[PROTECT]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance attacking pawn\n",ds); +#endif + } else if ( in_opening_stage ) { + s += (ds = 2*fv1[PROTECT]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance attacking non-pawn\n",ds); +#endif + } + } else { + /* bishop or rook pin attack */ + if ( board[u] == pawn ) { + s += (ds = -fv1[HCLSD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for enemy pawn in bishops direction\n",ds); +#endif + } + } + } +#ifdef SAVE_NEXTPOS + dd = d; + xu = next_position(ptyp,&d,sq,u); + if ( xu != next_direction(ptyp,&dd,sq) ) + pin = u; /* not on the edge and on to find a pin */ +#else + if ((xu = ppos[u]) != pdir[u]) + pin = u; /* not on the edge and on to find a pin */ +#endif + u = xu; + } + else + { + /* it's the second piece in the current direction */ +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file, + "second piece on square %d is an %s piece\n", + u, (color[u]==c1) ? "own" : "enemy"); +#endif + if ( color[u] == c1 ) { + /* second piece is an own piece */ + if ( upiece == bishop && board[u] == pawn && GameType[c1] == STATIC_ROOK ) { + s += (ds = -fv1[HCLSD]); +#ifdef DEBUG_EVAL + if (debug_eval ) + fprintf(debug_eval_file,"%d for own pawn in bishops (2) direction\n",ds); +#endif + } + } else { + /* second piece is an enemy piece */ + if ( upiece == bishop && board[u] == pawn ) { + s += (ds = -fv1[HCLSD]/2); +#ifdef DEBUG_EVAL + if (debug_eval ) + fprintf(debug_eval_file,"%d for enemy pawn in bishops (2) direction\n",ds); +#endif + } + if ((*value)[stage][xupiece = unpromoted[board[u]]] > rvalue || atk2[u] == 0) { +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"enemy %s better than attacking %s\n", + PieceStr[upiece], PieceStr[xupiece]); +#endif + if (color[pin] == c2) { + if ( xupiece == king && in_endgame_stage ) { + s += (ds = 2*fv1[PINVAL]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for pin attack to king\n",ds); +#endif + } else { + s += (ds = fv1[PINVAL]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for pin attack\n",ds); +#endif + } + if (atk2[pin] == 0 || atk1[pin] > control[board[pin]] + 1) { + hung[c2]++; + shung[u]++; + } + } else { + if ( upiece == lance ) { + s += (ds = fv1[XRAY]/2); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"lance xray attack: %d\n",ds); +#endif + } else { + s += (ds = fv1[XRAY]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"bishop/rook xray attack: %d\n",ds); +#endif + } + } + } + } + pin = -1; /* new direction */ +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,sq); +#else + u = pdir[u]; +#endif + } + } + } + while (u != sq); + *mob = mobx; + return s; +} + + + +#define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp) + + +inline +short int +KingScan (register short int sq) + +/* + * Assign penalties if king can be threatened by checks, if squares near the + * king are controlled by the enemy (especially by promoted pieces), + * or if there are no own generals near the king. + * The following must be true: + * board[sq] == king, c1 == color[sq], c2 == otherside[c1] + */ + + +#ifdef DEBUG_EVAL + +#define ScoreThreat \ + { if (color[u] != c2)\ + if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\ + ++cnt;\ + } else {\ + s += (ds = -fv1[CTRLK]);\ + if ( debug_eval ) \ + fprintf(debug_eval_file,"%d for squares near king controlled by enemy %s\n",\ + ds, PieceStr[p]);\ + }\ + } + +#else + +#define ScoreThreat \ + { if (color[u] != c2)\ + if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\ + ++cnt;\ + } else {\ + s += (ds = -fv1[CTRLK]);\ + }\ + } + +#endif + + +{ + register short cnt; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char far *ppos, *pdir; +#endif + register short int s; + register short u, ptyp; + short int ok, ds; +#ifdef DEBUG_EVAL + short s0; +#endif + + /* Penalties, if a king can be threatened by checks. */ + + s = 0; + cnt = 0; + { short p; + for ( p = pawn; p < king; p++ ) + if ( HasPiece[c2][p] || Captured[c2][p] ) + { short ptyp; + /* if a c1 piece can reach u from sq, + * then a c2 piece can reach sq from u. + * That means, each u is a square, from which a + * piece of type p and color c2 threats square sq. + */ + ptyp = ptype[c1][p]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + do + { + /* If a p piece can reach (controls or can drop to) + * square u, then score threat. + */ + if (atk2[u] & control[p]) + ScoreThreat + else if (Captured[c2][p] && color[u] == neutral) + ScoreThreat +#ifdef SAVE_NEXTPOS + u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u) + : next_direction(ptyp,&d,sq)); +#else + u = ((color[u] == neutral) ? ppos[u] : pdir[u]); +#endif + } + while (u != sq); + } + } + s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16); + +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for possible king threats\n",ds); +#endif + + /* Penalties, if squares near king are controlled by enemy. */ + + cnt = 0; + ok = false; + ptyp = ptype[c1][king]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + pdir = (*nextpos[ptyp])[sq]; + u = pdir[sq]; +#endif + do + { + if ( !ok && color[u] == c1 ) + { + short ptype_piece = ptype[black][board[u]]; + if ( ptype_piece == ptype_silver || ptype_piece == ptype_gold ) + ok = true; + } + if (atk2[u] > atk1[u]) + { + ++cnt; + if (atk2[u] & ctlSG) { + s += (ds = -fv1[KSFTY]/2); +#ifdef DEBUG_EVAL + if (debug_eval ) + fprintf(debug_eval_file,"%d square controlled by near enemy silver or gold\n",ds); +#endif + } + } +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,sq); +#else + u = pdir[u]; +#endif + } + while (u != sq); + if ( !ok || cnt > 1) { + if ( cnt > 1 ) + s += (ds = -fv1[KSFTY]/2); + else + s += (ds = -fv1[KSFTY]); +#ifdef DEBUG_EVAL + if (debug_eval ) + if ( !ok ) + fprintf(debug_eval_file,"%d for no general protect king\n",ds); + else + fprintf(debug_eval_file,"%d for %d enemy generals dear king\n",cnt,ds); +#endif + } + + return (s); +} + + +static short checked_trapped; + + +inline +int +trapped (register short int sq) + +/* + * See if the attacked piece has unattacked squares to move to. The following + * must be true: c1 == color[sq] c2 == otherside[c1] + */ + +{ + register short u, ptyp; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char far *ppos, *pdir; +#endif + register short int piece; + short rvalue; + + piece = board[sq]; + rvalue = (*value)[stage][piece]; + ptyp = ptype[c1][piece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + do { + if (color[u] != c1) + if (atk2[u] == 0 || (*value)[stage][board[u]] >= rvalue) + return (false); +#ifdef SAVE_NEXTPOS + u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u) + : next_direction(ptyp,&d,sq)); +#else + u = ((color[u] == neutral) ? ppos[u] : pdir[u]); +#endif + } while (u != sq); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"piece is trapped\n"); +#endif + checked_trapped = true; + + return (true); +} + + + +static int AttackedPieceValue (register short int sq, short int side) +{ + short s, ds; + + s = 0; + + ds += (ds = -fv1[HUNGP]); + hung[c1]++; + shung[sq]++; +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"attacked: %d, hung[%s]++\n", + ds, ColorStr[c1]); +#endif + + if (trapped (sq)) + { + hung[c1] += 2; + shung[sq] += 2; +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"trapped: hung[%s] += 2\n", + ColorStr[c1]); +#endif + } + + return s; +} + + + +static inline int +OpenFileValue (register short sq, short hopn, short hopnx) +{ + short s=0, fyle; + + if (PC1[fyle = column(sq)] == 0) + { + s += hopn; +#ifdef DEBUG_EVAL + if (debug_eval && hopn) + fprintf(debug_eval_file,"adding %d for now own pawn on file\n",hopn); +#endif + } + + if (PC2[fyle] == 0) + { + s += hopnx; +#ifdef DEBUG_EVAL + if (debug_eval && hopnx) + fprintf(debug_eval_file,"%d for no opponents pawn on file\n",hopnx); +#endif + } + + return s; +} + + +/* Distance bonus */ + +#ifdef DEBUG_EVAL + +#define PromotionZoneDistanceValue(sq,dd)\ + if ( ds = fv1[PROMD] ) { \ + s += (ds = ds * PromotionZoneDistanceBonus[crow(c1,sq)] * dd);\ + if (debug_eval && ds) \ + fprintf(debug_eval_file,"%d for distance to promotion zone\n",ds); \ + } + +#else + +#define PromotionZoneDistanceValue(sq,dd)\ + if ( ds = fv1[PROMD] ) { \ + s += (ds = ds * PromotionZoneDistanceBonus[crow(c1,sq)] * dd);\ + } + +#endif + + +#ifdef DEBUG_EVAL + +#define OwnKingDistanceValue(sq,dd,maxd)\ + if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd) ) { \ + s += (ds = ds * OwnKingDistanceBonus[ad] * dd);\ + if (debug_eval && ds) \ + fprintf(debug_eval_file,"%d for distance to own king\n",ds); \ + } + +#else + +#define OwnKingDistanceValue(sq,dd,maxd)\ + if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd) ) { \ + s += (ds = ds * OwnKingDistanceBonus[ad] * dd);\ + } + +#endif + + +#ifdef DEBUG_EVAL + +#define EnemyKingDistanceValue(sq,dd,maxd)\ + if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd) ) { \ + s += (ds = ds * EnemyKingDistanceBonus[ad] * dd);\ + if (debug_eval && ds) \ + fprintf(debug_eval_file,"%d for distance to enemy king\n",ds); \ + } + +#else + +#define EnemyKingDistanceValue(sq,dd,maxd)\ + if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd) ) { \ + s += (ds = ds * EnemyKingDistanceBonus[ad] * dd);\ + } + +#endif + + + + +static inline int +PawnValue (register short int sq, short int side) +/* + * Calculate the positional value for a pawn on 'sq'. + */ + +{ + register short s=0; + short ds; + short n; + short ccol = ccolumn(c1,sq); + + PromotionZoneDistanceValue(sq,3); + + /* pawn mobility */ + if ( color[(c1==black)?(sq+9):(sq-9)] == neutral ) { + s += (ds = MBLTY[pawn]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for mobility\n", ds); +#endif + } + + if ( (a1 & ((ctlR | ctlRp) | ctlL)) ) { + s += (ds = fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for rook/lance-supported pawn\n",ds); +#endif + } + + if ( in_opening_stage ) { + + if ( crow(c1,sq) == 2 ) /* pawn on 3d rank */ + if ( board[(c1==black)?(sq+27):(sq-27)] == pawn ) + { /* opposing pawn has been moved (even column == (sq & 1)) */ + short m; + switch ( ccol ) { + case 0: case 8: m = ( side == c1 ) ? 3 : 5; break; + case 4: m = ( side == c1 ) ? 2 : 3; break; + default:m = ( side == c1 ) ? 1 : 2; break; + } + s += (ds = -m*MBLTY[pawn]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for opposing pawn pushed\n",ds); +#endif + } + + if ( GameType[c1] == STATIC_ROOK && sq == csquare(c1,43) ) + if ( (atk2[csquare(c1,52)] & CNT_MASK) < 2 ) + { + s += (ds = fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for attacking pawn on 2nd col\n",ds); +#endif + } + + if ( GameType[c2] == STATIC_ROOK && ccol == 1 ) + { + if ( sq == csquare(c1,28) ) + { + s += (ds = -fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for pushed pawn on 8th file\n",ds); +#endif + } + if ( (atk1[csquare(c1,19)] & CNT_MASK) < 2 && (atk1[csquare(c1,28)] & CNT_MASK) < 2 ) + { + s += (ds = -2*fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for weak pawn on 8th col\n",ds); +#endif + } + } + + } + + return (s); +} + + +static inline int +LanceValue (register short int sq, short int side) +/* + * Calculate the positional value for a lance on 'sq'. + */ + +{ + register short s=0, ds, ad; + + OwnKingDistanceValue(sq,1,2); + + OpenFileValue (sq, -fv1[HOPN], fv1[HOPN]); + + if ( !checked_trapped && crow(c1,sq) > 2 ) + { + if (in_opening_stage || trapped (sq)) + { + s += (ds = -3*fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance in danger\n",ds); +#endif + } + else + { + s += (ds = -2*fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for lance in danger\n",ds); +#endif + } + } + + return (s); +} + +static inline int +KnightValue (register short int sq, short int side) +/* + * Calculate the positional value for a knight on 'sq'. + */ + +{ + register short s = 0, ad; + short ds, checked_trapped = false; + short c = column(sq); + + PromotionZoneDistanceValue(sq,1); + OwnKingDistanceValue(sq,1,2); + + if ( !checked_trapped && crow(c1,sq) > 2 ) + { + if (trapped (sq)) + { + s += (ds = -4*fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for knight in danger\n",ds); +#endif + } + else + { + s += (ds = -3*fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for knight in danger\n",ds); +#endif + } + } + + if ( c == 0 || c == 8 ) { + s += (ds = -fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for knight on edge file\n",ds); +#endif + } + + return (s); +} + +static inline int +SilverValue (register short int sq, short int side) +/* + * Calculate the positional value for a silver on 'sq'. + */ + +{ + register short s= 0, ds, ad; + + OwnKingDistanceValue(sq,2,3); + + if ( Kdist[c1][sq] < 3 && (atk1[sq] & (control[gold] | control[silver])) ) { + s += (ds = fv1[COHESION]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for good cohesion\n",ds); +#endif + } + + if ( in_opening_stage ) { + if ( GameType[c1] == STATIC_ROOK ) + if ( csquare(c1,sq) == 12 ) + { + short csq; + if ( board[csq = csquare(c1,20)] == bishop && color[csq] == c1 ) + { + s += (ds = -2*fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for wrong opening\n",ds); +#endif + } + } + } else { + EnemyKingDistanceValue(sq,2,3); + } + + return (s); +} + +static inline int +GoldValue (register short int sq, short int side) +/* + * Calculate the positional value for a gold on 'sq'. + */ + +{ + register short s=0, ds, ad; + + OwnKingDistanceValue(sq,2,3); + + if ( Kdist[c1][sq] < 3 && (atk1[sq] & (control[gold] | control[silver])) ) { + s += (ds = fv1[COHESION]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for good cohesion\n",ds); +#endif + } + + if ( in_opening_stage ) { + if ( GameType[c1] == STATIC_ROOK && GameType[c2] != STATIC_ROOK ) + if ( Mvboard[csquare(c1,3)] ) + { + s += (ds = -2*fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for wrong opening\n",ds); +#endif + } + } else { + EnemyKingDistanceValue(sq,2,3); + } + + return (s); +} + +static inline int +BishopValue (register short int sq, short int side) +/* + * Calculate the positional value for a bishop on 'sq'. + */ + +{ + register short s=0, ds, ad; + + if ( in_opening_stage ) { + if ( GameType[c1] == RANGING_ROOK ) + { + /* Bishops diagonal should not be open */ + if ( !on_csquare(c1,pawn,30) ) { + s += (ds = -fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for open bishops diagonal\n",ds); +#endif + } + } + else if ( GameType[c2] == RANGING_ROOK ) + { + /* Bishops diagonal should be open */ + if ( csquare(c1,sq) == 10 && + (!empty_csquare(c1,20) || !empty_csquare(c1,30)) ) { + s += (ds = -fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for closed bishops diagonal\n",ds); +#endif + } else if ( csquare(c1,sq) == 20 && !empty_csquare(c1,30) ) { + s += (ds = -fv1[OPENWRONG]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for closed bishops diagonal\n",ds); +#endif + } + } + } else { + EnemyKingDistanceValue(sq,1,3); + } + + return (s); +} + +static inline int +RookValue (register short int sq, short int side) +/* + * Calculate the positional value for a rook on 'sq'. + */ + +{ + register short s=0, ds, ad; + + OpenFileValue (sq, 2*fv1[HOPN], 4*fv1[HOPN]); + + if ( in_opening_stage ) { + short WRONG = fv1[OPENWRONG], OPOK = WRONG/3; + if ( GameType[c1] == STATIC_ROOK ) + { + short c = ccolumn(c1,sq); + /* Bonus for rook on 8th file */ + if ( c == 7 ) { + s += (ds = OPOK); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for rook on 8th file\n",ds); +#endif + } + /* Bonus for rook on right side, malus for rook on left side */ + c = 4 - c; ds = 0; + if ( c < 0 ) { + s += (ds = c + c + OPOK); + } else if ( c >= 0 ) { + s += (ds = -c - c - WRONG); + } +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for king on correct/wrong side\n",ds); +#endif + } + else if ( GameType[c1] == RANGING_ROOK ) + { + /* Bonus for rook on left side and bishops diagonal closed, malus otherwise. */ + short c; + c = 4 - ccolumn(c1,sq); ds = 0; + if ( c >= 0 ) { + /* Bishops diagonal should not be open */ + if ( on_csquare(c1,pawn,30) ) + s += (ds = OPOK); + else + s += (ds = -c - c - WRONG); + } else if ( c < 0 ) { + s += (ds = -c - c - WRONG); + /* Malus for king not on initial square */ + if ( !on_csquare(side,king,4) ) { + s += -4*WRONG; ds += -4*WRONG; + } + } +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for bishops diagonal\n",ds); +#endif + } + } else { + EnemyKingDistanceValue(sq,1,3); + } + + return (s); +} + +static inline int +PPawnValue (register short int sq, short int side) +/* + * Calculate the positional value for a promoted pawn on 'sq'. + */ + +{ + register short s = 0, ds, ad; + + EnemyKingDistanceValue(sq,3,10); + + return (s); +} + +static inline int +PLanceValue (register short int sq, short int side) +/* + * Calculate the positional value for a promoted lance on 'sq'. + */ + +{ + register short s = 0, ds, ad; + + EnemyKingDistanceValue(sq,3,10); + + return (s); +} + +static inline int +PKnightValue (register short int sq, short int side) +/* + * Calculate the positional value for a promoted knight on 'sq'. + */ + +{ + register short s = 0, ds, ad; + + EnemyKingDistanceValue(sq,3,10); + + return (s); +} + +static inline int +PSilverValue (register short int sq, short int side) +/* + * Calculate the positional value for a promoted silver on 'sq'. + */ + +{ + register short s = 0, ds, ad; + + EnemyKingDistanceValue(sq,3,10); + + return (s); +} + +static inline int +PBishopValue (register short int sq, short int side) +/* + * Calculate the positional value for a promoted bishop on 'sq'. + */ + +{ + register short s = 0, ds, ad; + + EnemyKingDistanceValue(sq,3,4); + + return (s); +} + +static inline int +PRookValue (register short int sq, short int side) +/* + * Calculate the positional value for a promoted rook on 'sq'. + */ + +{ + register short s = 0, ds, ad; + + EnemyKingDistanceValue(sq,3,4); + + OpenFileValue (sq, 3*fv1[HOPN], 2*fv1[HOPN]); + + return (s); +} + +static inline int +KingValue (register short int sq, short int side) +/* + * Calculate the positional value for a king on 'sq'. + */ +{ + register short s = 0, ds; + + if ( fv1[KSFTY] != 0 ) + s += KingScan (sq); + + if ( in_opening_stage ) + if ( GameType[c1] != UNKNOWN && ccolumn(c1,sq) == 4 ) { + s += (ds = -fv1[OPENWRONG]/3); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for center king\n",ds); +#endif + } else if ( GameType[c1] == STATIC_ROOK && on_right_side(c1,sq) ) { + s += (ds = -fv1[OPENWRONG]/2); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for king on right side\n",ds); +#endif + } else if ( GameType[c1] == RANGING_ROOK && on_left_side(c1,sq) ) { + s += (ds = -fv1[OPENWRONG]/2); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for king on left side\n",ds); +#endif + } + + if ( ds = fv1[HOPN] ) { + s += OpenFileValue(sq,-2*ds,-4*ds); + } + + return (s); +} + + + +static inline int +PieceValue (register short int sq, short int side) +/* + * Calculate the positional value for a piece on 'sq'. + */ + +{ + register short s, piece, ds; + short mob; + + piece = board[sq]; + + if ( piece == no_piece ) + return 0; + + s = (*Mpiece[piece])[c1][sq]; + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"\ninital value for %s %s on %c%c: %d\n", + ColorStr[c1], PieceStr[piece], cxx[column(sq)], rxx[row(sq)], s); +#endif + + checked_trapped = false; + + if ( sweep[piece] ) { + /* pin/xray attack and mobility for sweeping pieces */ + s += (ds = BRLscan (sq, &mob)); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d sum for sweeping piece\n", ds); +#endif + if ( piece == bishop || piece == pbishop ) + s += (ds = BMBLTY[mob] * fv1[MOBILITY] / 100); + else if ( piece == rook || piece == prook ) + s += (ds = RMBLTY[mob] * fv1[MOBILITY] / 100); + else + s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for mobility of sweeping piece\n", ds); +#endif + } else { + /* mobility for non-sweeping pieces */ + } + + a2 = atk2[sq]; + a1 = atk1[sq]; + + if (a2 > 0) + { /* opponent attacks piece */ + if (a1 == 0) + { /* undefended piece */ + s += AttackedPieceValue (sq, side); + } + else + { /* defended piece */ + short attack_value = value_of_weakest_attacker(a2); + short piece_value = (*value)[stage][piece]; + if ( attack_value < piece_value ) + { /* attacked by a weaker piece */ + s += AttackedPieceValue (sq, side) / 2; + } + else if ( abs(attack_value - piece_value) < 10 ) + { + /* opponent has the option to exchange equal pieces */ + s += (ds = -fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"exchange option: %d\n", ds); +#endif + } +#ifdef notdef + else if (a1 < ctlP) + { /* piece is not defended by a pawn */ + s += (ds = -fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"not defended by pawn: %d\n", ds); +#endif + } +#endif + } + } + + if ( piece != king ) { + + if ( a1 > 0 ) { + /* piece is defended */ + s += (ds = (a1 & CNT_MASK)*fv1[PROTECT]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for protected piece\n", ds); +#endif + } + + if ( sseed[sq] ) { + s += (ds = fv1[SEED]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for seed piece\n", ds); +#endif + } + + if ( sloose[sq] ) { + s += (ds = -fv1[LOOSE]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for loose piece\n", ds); +#endif + } + + if ( starget[c1][sq] ) { + if ( sweep[piece] ) { + s -= (ds = -fv1[ATAKD]/2); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for sweeping piece on own target square\n", ds); +#endif + } else if ( piece == pawn ) { + s += (ds = fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for pawn on own target square\n", ds); +#endif + } + } + + if ( starget[c2][sq] ) { + if ( piece != pawn ) { + s -= (ds = -fv1[ATAKD]/3); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for non-pawn on opponents target square\n", ds); +#endif + } else { + s += (ds = fv1[ATAKD]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for pawn on opponents target square\n", ds); +#endif + } + } + + if ( Kdist[c1][sq] == 1 ) { + s += (ds = fv1[KSFTY]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for piece near king\n", ds); +#endif + } + + } + + switch ( piece ) { + case pawn: + s += PawnValue (sq, side); + break; + case lance: + s += LanceValue (sq, side); + break; + case knight: + s += KnightValue (sq, side); + break; + case silver: + s += SilverValue (sq, side); + break; + case gold: + s += GoldValue (sq, side); + break; + case bishop: + s += BishopValue (sq, side); + break; + case rook: + s += RookValue (sq, side); + break; + case king: + s += KingValue (sq, side); + break; + case ppawn: + s += PPawnValue (sq, side); + break; + case plance: + s += PLanceValue (sq, side); + break; + case pknight: + s += PKnightValue (sq, side); + break; + case psilver: + s += PSilverValue (sq, side); + break; + case pbishop: + s += PBishopValue (sq, side); + break; + case prook: + s += PRookValue (sq, side); + break; + } + + return (s); +} + + +short +ScorePatternDistance (short c1) + +/* + * Score distance to pattern regarding the game type which side plays. + */ + +{ + short ds, s = 0; + small_short *fv1 = fvalue[c1]; + short os = 0; + +#ifdef DEBUG_EVAL + char name[16]; + if ( debug_eval ) + fprintf(debug_eval_file,"scoring castle pattern distance for PCASTLE=%d\n", + fv1[PCASTLE]); +#endif + + if ( MAXCDIST > 0 && fv1[PCASTLE] != 0 && ((os = castle_opening_sequence[c1]) >= 0) ) + { + ds = board_to_pattern_distance(c1,os,MAXCDIST,GameCnt); + if ( ds != 0) { + s += (ds *= fv1[PCASTLE]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds != 0 ) { + NameOfOpeningValue(OpeningSequence[os].opening_type,name); + fprintf(debug_eval_file, + "add %d for max gain of %s to reachable castle patterns %s\n", + ds, ColorStr[c1], name); + } +#endif + }; + } +#ifdef DEBUG_EVAL + else if ( debug_eval && os<0 ) + fprintf(debug_eval_file,"no castle pattern for %s\n",ColorStr[c1]); +#endif + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"scoring attack pattern distance for PATTACK=%d\n", + fv1[PATTACK]); +#endif + + if ( MAXADIST > 0 && fv1[PATTACK] != 0 && ((os = attack_opening_sequence[c1]) >= 0) ) + { + ds = board_to_pattern_distance(c1,os,MAXADIST,GameCnt); + if ( ds != 0 ) { + s += (ds *= fv1[PATTACK]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds != 0 ) { + NameOfOpeningValue(OpeningSequence[os].opening_type,name); + fprintf(debug_eval_file, + "add %d for max gain of %s to reachable attack patterns %s\n", + ds, ColorStr[c1], name); + } +#endif + } + } +#ifdef DEBUG_EVAL + else if ( debug_eval && os<0 ) + fprintf(debug_eval_file,"no attack pattern for %s\n",ColorStr[c1]); +#endif + + return(s); +} + + + +static +void +UpdatePatterns (short int side, short int GameCnt) + +/* + * Determine castle and attack pattern which should be reached next. + * Only patterns are considered, which have not been reached yet. + */ + +{ + char s[12]; + short xside = side ^ 1; + short os; + short i, j, k, n = 0; +#ifdef DEBUG_EVAL + char name[16]; +#endif + + strcpy(s,"CASTLE_?_?"); + s[7] = GameType[side]; + s[9] = GameType[xside]; + castle_opening_sequence[side] = os = locate_opening_sequence(side,s,GameCnt); + + if ( flag.post && os!=END_OF_SEQUENCES ) + { + for (j=0; j= 0 ) n++; + } + } + + if ( os!=END_OF_SEQUENCES ) update_advance_bonus (side,os); + +#ifdef DEBUG_EVAL + if ( debug_eval ) + if (os!=END_OF_SEQUENCES ) + { + NameOfOpeningValue(OpeningSequence[os].opening_type,name); + fprintf(debug_eval_file,"castle pattern of %s is %s\n", + ColorStr[side], name); + fprintf(debug_eval_file,"reachable patterns: "); + for (j=0; j= 0 ) + fprintf(debug_eval_file,"%d(%d) ",i,j); + fprintf(debug_eval_file,"\n"); + } + else + { + fprintf(debug_eval_file,"no castle pattern %s for %s\n", + s, ColorStr[side]); + } +#endif + + strcpy(s,"ATTACK_?_?"); + s[7] = GameType[side]; + s[9] = GameType[xside]; + attack_opening_sequence[side] = os = locate_opening_sequence(side,s,GameCnt); + + if ( flag.post && os!=END_OF_SEQUENCES ) + { + for (j=0; j= 0 ) n++; + } + } + + if ( flag.post ) + { + ShowPatternCount(side,n); + } + + if ( os!=END_OF_SEQUENCES ) update_advance_bonus (side,os); + +#ifdef DEBUG_EVAL + if ( debug_eval ) + if ( os!=END_OF_SEQUENCES ) + { + NameOfOpeningValue(OpeningSequence[os].opening_type,name); + fprintf(debug_eval_file,"attak pattern of %s is %s\n", + ColorStr[side], name); + fprintf(debug_eval_file,"reachable patterns: "); + for (j=0; j= 0 ) + fprintf(debug_eval_file,"%d(%d) ",i,j); + fprintf(debug_eval_file,"\n"); + } + else + { + fprintf(debug_eval_file,"no attak pattern %s for %s\n", + s, ColorStr[side]); + } +#endif + + +} + + + + +static +void +ScoreSquares (void) +{ + register short sq; + short ds, n, m; + + for ( sq = 0; sq < NO_SQUARES; sq++ ) { + + for ( c1 = black, c2 = white; c1 <= white; c1++, c2-- ) { + + a1 = atak[c1][sq]; + a2 = atak[c2][sq]; + fv1 = fvalue[c1]; + + if ( InPromotionZone(c1,sq) ) { + /* square in promotion zone */ + if ( a1 & control[pawn] ) { + /* dangling pawn */ + pscore[c1] += (ds = 2*fv1[DNGLPC]); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for %s dangling pawn\n",ds,ColorStr[c1]); + } +#endif + } + if ( a1 & (control[lance] | control[knight]) ) { + /* dangling lance or dangling knight */ + pscore[c1] += (ds = fv1[DNGLPC]); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for %s dangling knight/silver\n",ds,ColorStr[c1]); + } +#endif + } + } + if ( a1 & control[king] ) { + /* square controlled by own king */ + if ( (n = a1 & CNT_MASK) > 1 ) { + pscore[c1] += (ds = (n-1)*fv1[KNGPROTECT]); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for %s protects own king\n",ds,ColorStr[c1]); + } +#endif + } + } + if ( a2 & control[king] ) { + /* square controlled by enemy king */ + if ( (n = a1 & CNT_MASK) > 0 ) { + pscore[c1] += (ds = n*fv1[KNGATTACK]); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for %s controls enemy king\n",ds,ColorStr[c1]); + } +#endif + } + } + if ( (a2 & CNT_MASK) > 1 ) { + /* enemy's focal point */ + if ( (n = a1 & CNT_MASK) > 0 ) { + pscore[c1] += (ds = n*fv1[FCLATTACK]); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for %s attacks enemy's focal point\n",ds,ColorStr[c1]); + } +#endif + } + } + } + + if ( (c1 = color[sq]) == neutral ) { + + /* empty square */ + + } else { + + /* occupied square */ + + c2 = c1 ^ 1; + + a1 = atak[c1][sq]; + a2 = atak[c2][sq]; + fv1 = fvalue[c1]; + + if ( a2 && sloose[sq] ) { + pscore[c2] += (ds = fv1[LSATTACK]); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for %s attacks loose piece\n",ds,ColorStr[c2]); + } +#endif + } + if ( a2 && !Captured[c2][unpromoted[board[sq]]] ) { + pscore[c2] += (ds = fv1[NIHATTACK]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) { + fprintf(debug_eval_file,"%d for %s attack piece not in hand\n",ds,ColorStr[c2]); + } +#endif + } + } + + } + +} + + + +static +void +ScoreCaptures (void) +{ + short ds, col, n, m, piece; + + if ( n = Captured[c1][pawn] ) { + ds = m = 0; + for ( col = 0; col < NO_COLS; col++ ) { + if ( !PC1[col] ) { + m++; + ds += fv1[PWNDROP]; + } + } + pscore[c1] += (ds *= ((n > 2) ? 3 : n)); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) { + fprintf(debug_eval_file,"%d for %s %d captured pawns dropable to %d cols\n", + ds,ColorStr[c2],n,m); + } +#endif + } + + if ( m = seed[c1] ) { + for ( piece = lance, n=0; piece <= rook; piece++ ) { + if ( Captured[c1][piece] ) + n++; + } + pscore[c1] += (ds = m*fv1[DFFDROP]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) { + fprintf(debug_eval_file,"%d for %s %d diff captures supported by %d seed pieces\n", + ds,ColorStr[c2],n,m); + } +#endif + } + + for ( piece = pawn, n = 0; piece <= rook; piece++ ) { + if ( Captured[c1][piece] ) { + switch ( piece ) { + case bishop: ds = BMBLTY[MAX_BMBLTY-1]; break; + case rook : ds = RMBLTY[MAX_RMBLTY-1]; break; + case lance : ds = LMBLTY[MAX_LMBLTY-1]; break; + default : ds = MBLTY[piece]; + } + pscore[c1] += ds; +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) { + fprintf(debug_eval_file,"%d for %s's piece %s in hand mobility\n", + ds,ColorStr[c2],PieceStr[piece]); + } +#endif + if ( !Captured[c2][piece] ) + n += relative_value[piece]; + } + } + if ( n ) { + pscore[c1] += (ds = -n*fv1[OPPDROP]/2); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) { + fprintf(debug_eval_file,"%d for %s's captured pieces not in %s's hand\n", + ds,ColorStr[c2],ColorStr[c1]); + } +#endif + } + +} + + + + +short int +ScorePosition (register short int side) + +/* + * Perform normal static evaluation of board position. A score is generated + * for each piece and these are summed to get a score for each side. + */ + +{ + register short int score; + register short sq, i, xside; + short int s; + short int escore; + short int ds; + + xside = side ^ 1; + + UpdateWeights (side); + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf (debug_eval_file, "side = %s, stage = %d, in_opening = %d\n", + ColorStr[side], stage, in_opening_stage ); +#endif + + hung[black] = hung[white] = pscore[black] = pscore[white] = 0; + + array_zero(shung,sizeof(shung)); + +#ifdef CACHE +#ifdef DEBUG_EVAL + if (debug_eval || !(use_etable && ProbeEETable (side, &s))) +#else + if (!(use_etable && ProbeEETable (side, &s))) +#endif + { +#endif + for (c1 = black; c1 <= white; c1++) + { + c2 = c1 ^ 1; + /* atk1 is array of atacks on squares by my side */ + atk1 = atak[c1]; + /* atk2 is array of atacks on squares by other side */ + atk2 = atak[c2]; + /* same for PC1 and PC2 */ + PC1 = PawnCnt[c1]; + PC2 = PawnCnt[c2]; + /* same for fv1 and fv2 */ + fv1 = fvalue[c1]; + for (i = PieceCnt[c1]; i >= 0; i--) + { + sq = PieceList[c1][i]; +#if defined SAVE_SVALUE + pscore[c1] += PieceValue(sq,side); +#else + pscore[c1] += (svalue[sq] = PieceValue(sq,side)); +#endif + } + ScoreCaptures(); + } +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"pscore[%s] = %d, pscore[%s] = %d\n", + ColorStr[side], pscore[side], ColorStr[xside], pscore[xside]); +#if !defined SAVE_SVALUE + debug_svalue(debug_eval_file); +#endif + } +#endif +#ifdef DEBUG_EVAL + if ( debug_eval ) { + char buffer[80]; + sprintf(buffer,"%d Black and %d White HUNG PIECES",hung[black],hung[white]); + debug_table (debug_eval_file,shung,buffer); + } +#endif + for ( c1=black,c2=white; c1<=white; c1++,c2-- ) + { + short n; + + fv1 = fvalue[c1]; + + /* Score fifth rank */ + for ( sq = 36, n=0; sq <= 44; sq++ ) + if ( color[sq] == c1 || atak[c1][sq] != 0 ) + n++; + + if ( n != 0 ) { + pscore[c1] += (ds = n*fv1[CNTRL5TH]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for %s controls 5th rank with %d points\n", + ds, ColorStr[c1], n); +#endif + } + + /* Score holes */ + for ( sq = ((c1==black)?0:54), n=0; sq<=((c1==black)?26:80); sq++ ) + if ( board[sq] == no_piece && atak[c1][sq] == 0 ) + n++; + + if ( n != 0 ) { + pscore[c1] += (ds = -n*fv1[HOLES]); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for %s camp has %d holes\n", + ds, ColorStr[c1], n); +#endif + } + + if (hung[c1] > 1) { + pscore[c1] += (ds = -fv1[HUNGX]); +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"%d for %d hung pieces.\n", + ds, hung[c1]); +#endif + } + /* Score opening features and castle/attack pattern distances */ + + if ( in_opening_stage ) { + pscore[c1] += (ds = ScoreKingOpeningFeatures ()); +#ifdef DEBUG_EVAL + if ( debug_eval && ds) + fprintf(debug_eval_file,"%d for %s opening features\n", + ds, ColorStr[c1]); +#endif + pscore[c1] += (ds = ScorePatternDistance (c1)); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) + fprintf(debug_eval_file,"%d for %s pattern distance\n", + ds, ColorStr[c1]); +#endif + } + } + + score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10; + +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"side=%s xside=%s %d - %d + %d - %d + 10 = %d\n", + ColorStr[side], ColorStr[xside], + mtl[side], mtl[xside], pscore[side], pscore[xside], score); + } +#endif + +#ifdef notdef + if (dither) + { + if (flag.hash) + gsrand (starttime + (unsigned int) hashbd); + score += urand () % dither; + } +#endif + +#ifdef CACHE + if ( use_etable && PUTVAR ) + PutInEETable(side,score); +#endif +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf (debug_eval_file, "score = %d\n", score); +#endif + return(score); +#ifdef CACHE + } +#ifdef DEBUG_EVAL + else + { + if ( debug_eval ) + fprintf (debug_eval_file, "Score cached!\n" ); + } +#endif + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf (debug_eval_file, "s = %d\n", s); +#endif + return (s); +#endif + +} + + + +inline static void +GuessGameType (short side_to_move) +{ + /* + * Try to determine the game type of "side". + */ + + short side, sq, gt, StaticRook[2] = {0,0}, RangingRook[2] = {0,0}; + + for ( side=black; side<=white; side++ ) { + + /* computer should not change its mind */ + + extern int bookflag; + + gt = GameType[side]; + + if ( !bookflag && side == side_to_move ) + if ( gt == STATIC_ROOK ) + StaticRook[side] += 4; + else if ( gt == RANGING_ROOK ) + RangingRook[side] += 4; + + /* static rook conditions */ + + if ( on_column(side,rook,7) ) + StaticRook[side] += 3; + if ( on_csquare(side,pawn,34) ) + StaticRook[side] += 6; + else if ( on_csquare(side,pawn,43) ) + StaticRook[side] += 4; + else if ( !on_column(side,pawn,7) ) + StaticRook[side] += 5; + if ( empty_csquare(side,5) || empty_csquare(side,6) ) + StaticRook[side] += 2; + if ( on_left_side(side,king) ) + StaticRook[side] += 2; + + /* ranging rook conditions */ + + if ( on_left_side(side,rook) ) + RangingRook[side] += 5; + else if ( !on_column(side,rook,7) ) + RangingRook[side] += 3; + if ( on_csquare(side,pawn,25) ) + RangingRook[side] += 1; + if ( on_csquare(side,pawn,30) ) + RangingRook[side] += 1; + else + RangingRook[side] -= 2; + if ( !on_right_side(side,rook) ) + RangingRook[side] += 4; + if ( on_right_side(side,king) ) + RangingRook[side] += 4; + if ( on_csquare(side,bishop,20) ) + if ( on_csquare(side,silver,11) || on_csquare(side,silver,12) || + on_csquare(side,silver,21) ) + RangingRook[side] += 3; + + if ( StaticRook[side] > 5 || RangingRook[side] > 5 ) + GameType[side] = (StaticRook[side] > RangingRook[side]) + ? STATIC_ROOK : RANGING_ROOK; + else + GameType[side] = UNKNOWN; + + } + +#ifdef DEBUG_EVAL +#define StringOfGameType(side)\ + (GameType[side] == STATIC_ROOK ? "Static Rook" :\ + (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN")) + + if ( debug_eval ) + fprintf(debug_eval_file,"guessing game type: %s vs. %s\n", + StringOfGameType(black), StringOfGameType(white)); +#endif + + if ( GameType[black] == UNKNOWN || GameType[white] == UNKNOWN ) + { + for (side = black; side <= white; side++) + if ( side == computer && GameType[side] == UNKNOWN ) { + /* + * Game type is UNKNOWN. + * Make a decision what type of game to play. + * To make computer games more interesting, make a + * random decision. + */ + if ( !on_csquare(side,pawn,25) ) { + /* Play static rook if rook pawn has been pushed! */ + GameType[side] = STATIC_ROOK; + } else { + unsigned int random = urand () % 100; + short d = StaticRook[side] - RangingRook[side]; + switch ( GameType[side ^ 1] ) { + case STATIC_ROOK: + if ( random < 35 + d ) GameType[side] = STATIC_ROOK; + else if ( random < 95 ) GameType[side] = RANGING_ROOK; + break; + case RANGING_ROOK: + if ( random < 75 + d) GameType[side] = STATIC_ROOK; + else if ( random < 95 ) GameType[side] = RANGING_ROOK; + break; + default: + if ( random < 33 + d) GameType[side] = STATIC_ROOK; + else if ( random < 66 ) GameType[side] = RANGING_ROOK; + } + } +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"decide game type: %s vs. %s\n", + StringOfGameType(black), StringOfGameType(white)); +#endif + } + } + +} + + +#ifdef DEBUG_EVAL + +#define StringOfGameType(side)\ + (GameType[side] == STATIC_ROOK ? "Static Rook" :\ + (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN")) + +#endif + + +static +void +DetermineGameType (short side_to_move) +{ + short int side; + + GuessGameType(side_to_move); + +#if !defined XSHOGI + if ( flag.post ) + ShowGameType(); +#endif + + array_zero (Mpawn, sizeof(Mpawn)); + array_zero (Mlance, sizeof(Mlance)); + array_zero (Mknight, sizeof(Mknight)); + array_zero (Msilver, sizeof(Msilver)); + array_zero (Mgold, sizeof(Mgold)); + array_zero (Mbishop, sizeof(Mbishop)); + array_zero (Mrook, sizeof(Mrook)); + array_zero (Mking, sizeof(Mking)); + + if ( in_opening_stage ) { + for (side = black; side <= white; side++) + UpdatePatterns (side, GameCnt); + } else { + ShowPatternCount(black,-1); + ShowPatternCount(white,-1); + } + +} + +void +ExaminePosition (short side) + +/* + * This is done one time before the search is started. Set up arrays Mwpawn, + * Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function + * to determine the positional value of each piece. + */ + +{ + register short c1, piece, sq, i, bsq, wsq; + + /* Build enemy king distance tables. */ + + for (sq = 0, bsq = BlackKing, wsq = WhiteKing; sq < NO_SQUARES; sq++) + { + Kdist[black][sq] = distance(sq,bsq); + Kdist[white][sq] = distance(sq,wsq); + } + + threats (black); + threats (white); + + ExamineSquares(); + + DetermineGameType(side); + DetermineStage(side); + + UpdateWeights(side); + + array_zero (HasPiece, sizeof(HasPiece)); + + for (c1 = black; c1 <= white; c1++) + for (i = PieceCnt[c1]; i >= 0; i--) + { + ++HasPiece[c1][piece=board[sq=PieceList[c1][i]]]; + } + +#ifdef DEBUG_EVAL + if ( debug_eval ) + for (c1=black; c1<=white; c1++) + { + fprintf(debug_eval_file,"%s's tables\n\n",ColorStr[c1]); + debug_table(debug_eval_file,Mpawn[c1],"pawn"); + debug_table(debug_eval_file,Mlance[c1],"lance"); + debug_table(debug_eval_file,Mknight[c1],"knight"); + debug_table(debug_eval_file,Msilver[c1],"silver"); + debug_table(debug_eval_file,Mgold[c1],"gold"); + debug_table(debug_eval_file,Mbishop[c1],"bishop"); + debug_table(debug_eval_file,Mrook[c1],"rook"); + debug_table(debug_eval_file,Mking[c1],"king"); + debug_table(debug_eval_file,Kdist[c1],"distance to king"); + } +#endif + +} + + + + +void +DetermineStage (short side) + +{ + short xside = side ^ 1, ds, db1, db2, c1,c2, feature; + + /* Determine initial stage */ + + balance[side] = balance[xside] = 50; + + if ( GameType[side] == STATIC_ROOK && GameType[xside] == STATIC_ROOK ) { + if ( GameCnt < 40 ) + stage = 0; + else if ( GameCnt < 60 ) + stage = 15; + else if ( GameCnt < 80 ) + stage = 25; + else + stage = 30; + } else if ( GameType[side] == RANGING_ROOK || GameType[xside] == RANGING_ROOK ) { + if ( GameCnt < 30 ) + stage = 0; + else if ( GameCnt < 50 ) + stage = 15; + else if ( GameCnt < 70 ) + stage = 25; + else + stage = 30; + } else { + if ( GameCnt < 35 ) + stage = 0; + else if ( GameCnt < 55 ) + stage = 15; + else if ( GameCnt < 75 ) + stage = 25; + else + stage = 30; + } + +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"initial stage value = %d\n",stage); + fprintf(debug_eval_file,"initial balance values = %d,%d\n", + balance[0], balance[1]); + } +#endif + + /* Update stage depending on board features and attack balance value */ + + if ( abs(ds = (mtl[side] - mtl[xside])) > (db1 = (*value)[stage][lance]) ) { + db1 = abs(4 * ds / db1); + if ( ds < 0 ) { + balance[side] += db1; + } else if ( ds > 0 ) { + balance[xside] += db1; + }; + stage += (ds = db1); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d stage bonus for material balance\n",ds); + fprintf(debug_eval_file,"%d %s balance bonus for material balance\n", + db1, ColorStr[side]); + } +#endif + } + + for ( c1=black, c2=white; c1<=white; c1++, c2-- ) { + + if ( (ds = seed[c1]) > 2 ) { + balance[c1] += (db1 = ds * 2); + balance[c2] -= db1; + if ( stage < 30 ) + stage = 30; + stage += ds; +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d for seed pieces\n",ds); + fprintf(debug_eval_file,"%d %s balance bonus for seed pieces\n", + db1, ColorStr[c1]); + fprintf(debug_eval_file,"%d %s balance penalty for seed pieces\n", + -db1, ColorStr[c2]); + } +#endif + } + + if ( (db1 = hung[c1]) > 2 ) { + balance[c1] -= (db1 *= 2); + balance[c2] += db1; +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d %s balance penalty for hung pieces\n", + -db1, ColorStr[c1]); + fprintf(debug_eval_file,"%d %s balance bonus for hung pieces\n", + db1, ColorStr[c2]); + } +#endif + } + + if ( (db1 = loose[c1]) > 4 ) { + balance[c1] -= (db1 /= 2); + balance[c2] += db1; + stage += (ds = 1); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d stage bonus for loose piece\n",ds); + fprintf(debug_eval_file,"%d %s balance penalty for loose pieces\n", + -db1, ColorStr[c1]); + fprintf(debug_eval_file,"%d %s balance bonus for loose pieces\n", + db1, ColorStr[c2]); + } +#endif + } + + if ( (ds = hole[c1]) ) { + balance[c1] -= (db1 = ds); + balance[c2] += db1; + stage += (ds /= 2); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d stage bonus for holes\n",ds); + fprintf(debug_eval_file,"%d %s balance penalty for holes\n", + -db1, ColorStr[c1]); + fprintf(debug_eval_file,"%d %s balance bonus for holes\n", + db1, ColorStr[c2]); + } +#endif + } + + if ( (db1 = target[c1]) > 3 ) { + balance[c1] += (db1 /= 3); + balance[c2] -= db1; + stage += (ds = db1 / 4); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d stage bonus for targets\n",ds); + fprintf(debug_eval_file,"%d %s balance bonus for targets\n", + db1, ColorStr[c1]); + fprintf(debug_eval_file,"%d %s balance penalty for targets\n", + -db1, ColorStr[c2]); + } +#endif + } + + stage += (ds = captured[c1]/2); +#ifdef DEBUG_EVAL + if ( debug_eval && ds ) { + fprintf(debug_eval_file,"%d stage bonus for captured pieces\n",ds); + } +#endif + + if ( (db1 = captured[c1]) > 4 ) { + balance[c1] += (db1 /= 2); + stage += (ds = 3); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d stage bonus for pieces in hand\n",ds); + fprintf(debug_eval_file,"%d %s balance bonus for pieces in hand\n", + db1, ColorStr[c1]); + } +#endif + } + + if ( (db1 = dcaptured[c1]) > 3 ) { + balance[c1] += db1; + stage += (ds = 3); +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"%d stage bonus for different piece types in hand\n",ds); + fprintf(debug_eval_file,"%d %s balance bonus for different piece types in hand\n", + db1, ColorStr[c1]); + } +#endif + } + + if ( balance[c1] > 99 ) balance[c1] = 99; + else if ( balance[c1] < 0 ) balance[c1] = 0; + + } + +#ifdef DEBUG_EVAL + if ( debug_eval ) + for ( c1 = black; c1 <= white; c1++ ) + fprintf(debug_eval_file,"balance[%s] = %d\n",ColorStr[c1],balance[c1]); +#endif + + if ( stage > 99 ) stage = 99; + else if ( stage < 0 ) stage = 0; + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"stage = %d\n",stage); + +#endif + + if ( flag.post ) + ShowStage (); + + /* Determine stage dependant weights */ + + ADVNCM[pawn] = 1; /* advanced pawn bonus increment*/ + ADVNCM[lance] = 1; + ADVNCM[knight] = 1; + ADVNCM[silver] = 1; /* advanced silver bonus increment */ + ADVNCM[gold] = 1; /* advanced gold bonus increment */ + ADVNCM[bishop] = 1; + ADVNCM[rook] = 1; + ADVNCM[king] = 1; /* advanced king bonus increment */ + + MAXCDIST = (stage < 33 ) ? (33 - stage)/4 : 0; + MAXADIST = (stage < 30 ) ? (30 - stage)/4 : 0; + +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"maximum distance to castle pattern: %d\n",MAXCDIST); + fprintf(debug_eval_file,"maximum distance to attack pattern: %d\n",MAXADIST); + } +#endif + + for ( c1 = black; c1 <= white; c1++ ) { + for ( feature = 0; feature < NO_FEATURES; feature++ ) { + fvalue[c1][feature] = + ((((*fscore)[stage][feature][0] * (99 - balance[c1])) + 50) / 100) + + ((((*fscore)[stage][feature][1] * balance[c1]) + 50) / 100); + } + } + +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file,"weighted and balanced feature values\n"); + fprintf(debug_eval_file," Black White\n"); + for ( feature = 0; feature < NO_FEATURES; feature++ ) { + fprintf(debug_eval_file,"%3d %5d %5d\n", + feature,fvalue[0][feature],fvalue[1][feature]); + } + } +#endif +} + + +void +UpdateWeights (short stage) +{ +} + + +/* + * Compute stage dependent relative material values assuming + * linearity between the main stages: + * + * minstage < stage < maxstage => + * stage - minstage value - minvalue + * ------------------- = ------------------- + * maxstage - minstage maxvalue - minvalue + */ + + +static short linear_piece_value (short piece, short stage, short i, short j) +{ + short minvalue, maxvalue, minstage, maxstage; + minstage = ispvalue[0][i]; + maxstage = ispvalue[0][j]; + minvalue = ispvalue[piece][i]; + maxvalue = ispvalue[piece][j]; + return ((stage-minstage)*(maxvalue-minvalue)/(maxstage-minstage))+minvalue; +} + +static short linear_feature_value (short feature, short stage, short i, short j) +{ + short minvalue, maxvalue, minstage, maxstage; + minstage = ispvalue[0][i]; + maxstage = ispvalue[0][j]; + minvalue = weight[feature][i]; + maxvalue = weight[feature][j]; + return ((stage-minstage)*(maxvalue-minvalue)/(maxstage-minstage))+minvalue; +} + + +/* + * matweight = percentage_of_max_value * max_value(stage) / 100 + * max_value(0) = MAX_VALUE; max_value(100) = MIN_VALUE + * => max_value(stage) = a*stage+b; b=MAX_VALUE, a=(MIN_VALUE-MAX_VALUE)/100 + */ + +#define MIN_VALUE 300 +#define MAX_VALUE 1000 + +#define max_value(stage) ((long)(MIN_VALUE - MAX_VALUE) * stage + (long)100 * MAX_VALUE) +#define matweight(value,stage) ((long)max_value(stage) * value / 10000) + + +void +Initialize_eval (void) +{ + register short stage, piece, feature, i; + + for ( stage = 0; stage < NO_STAGES; stage++ ) { + for ( i = 0; i < MAIN_STAGES; i++ ) { + if ( stage == ispvalue[0][i] ) { + for ( piece = 0; piece < NO_PIECES; piece++ ) + (*value)[stage][piece] = + matweight(ispvalue[piece][i],stage); + for ( feature = 0; feature < NO_FEATURES; feature++ ) { + (*fscore)[stage][feature][0] = + (weight[feature][i] * weight[feature][MAIN_STAGES] + 50) / 100; + (*fscore)[stage][feature][1] = + (weight[feature][i] * weight[feature][MAIN_STAGES+1] + 50) / 100; + } + break; + } if ( stage < ispvalue[0][i+1] ) { + for ( piece = 0; piece < NO_PIECES; piece++ ) + (*value)[stage][piece] = + matweight(linear_piece_value(piece,stage,i,i+1),stage); + for ( feature = 0; feature < NO_FEATURES; feature++ ) { + (*fscore)[stage][feature][0] = + (linear_feature_value(feature,stage,i,i+1) + * weight[feature][MAIN_STAGES] + 50) /100; + (*fscore)[stage][feature][1] = + (linear_feature_value(feature,stage,i,i+1) + * weight[feature][MAIN_STAGES+1] + 50) /100; + } + break; + } + } + } + +#ifdef DEBUG_EVAL + debug_eval = ((debug_eval_file = fopen(EVALFILE,"w")) != NULL); + if ( debug_eval ) { + fprintf(debug_eval_file,"stage dependent absolute material values\n\n"); + fprintf(debug_eval_file," # - P L N S G B R +P +L +N +S +B +R K\n"); + for ( stage = 0; stage < NO_STAGES; stage++ ) { + fprintf(debug_eval_file,"%3d:",stage); + for ( piece = 0; piece < NO_PIECES; piece++ ) { + fprintf(debug_eval_file,"%4d",(*value)[stage][piece]); + } + fprintf(debug_eval_file,"\n"); + } + fprintf(debug_eval_file,"\n"); + fprintf(debug_eval_file,"stage dependent absolute feature scores\n\n"); + fprintf(debug_eval_file," # "); + for ( feature = 0; feature < NO_FEATURES; feature++ ) + fprintf(debug_eval_file,"%5d ",feature); + fprintf(debug_eval_file,"\n"); + for ( stage = 0; stage < NO_STAGES; stage++ ) { + fprintf(debug_eval_file,"%3d:",stage); + for ( feature = 0; feature < NO_FEATURES; feature++ ) { + fprintf(debug_eval_file," %3d,%3d", + (*fscore)[stage][feature][0], (*fscore)[stage][feature][1]); + } + fprintf(debug_eval_file,"\n"); + } + fprintf(debug_eval_file,"\n"); + fclose(debug_eval_file); + debug_eval = false; + }; +#endif +} + diff --git a/src/eval.h b/src/eval.h new file mode 100644 index 0000000..2eafcff --- /dev/null +++ b/src/eval.h @@ -0,0 +1,59 @@ +/* + * eval.h - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define NO_STAGES 100 +#define NO_FEATURES 31 + + + struct signature + { + unsigned long hashbd; + unsigned long hashkey; + } ; + +#define MatchSignature(s) (s.hashbd == hashbd && s.hashkey == hashkey) +#define CopySignature(s) {s.hashbd = hashbd; s.hashkey = hashkey;} + +typedef short value_array[NO_STAGES][NO_PIECES]; +typedef small_short fscore_array[NO_STAGES][NO_FEATURES][2]; + + extern value_array far *value; + extern fscore_array far *fscore; + + extern void threats (short int side); + + extern long int atak[2][NO_SQUARES]; + extern small_short sseed[NO_SQUARES]; + + extern struct signature threats_signature[2]; + + extern small_short starget[2][NO_SQUARES]; + extern small_short sloose[NO_SQUARES]; + extern small_short shole[NO_SQUARES]; + extern small_short shung[NO_SQUARES]; + + extern struct signature squares_signature; diff --git a/src/genmove.c b/src/genmove.c new file mode 100644 index 0000000..0aa505e --- /dev/null +++ b/src/genmove.c @@ -0,0 +1,1478 @@ +/* + * genmoves.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" + +/* #define DONTUSE_HEURISTIC */ + +#ifdef DEBUG +#include +#endif + +short *TrP; + +static struct leaf far *node; +static short sqking, sqxking; +static short InCheck = false, GenerateAllMoves = false; +static short check_determined = false; + +static short INCscore = 0; + +short deepsearchcut = true; +short tas = false, taxs = false, ssa = false; + +short generate_move_flags = false; + + +/* + * Ply limits for deep search cut. + * No moves or drops flagged with "stupid" are considered beyond ply BEYOND_STUPID. + * Only moves or drops flagged with "kingattack" are considered beyond ply BEYOND_KINGATTACK. + * No moves or drops flagged with "questionable" are considered beyond ply BEYOND_QUESTIONABLE. + * Only moves or drops flagged with "tesuji" are considered beyond ply BEYOND_TESUJI. + * No drops are considered beyond ply BEYOND_DROP. + * Exceptions: moves or drops that prevent check or give check are always considered. + */ + +#if defined THINK_C || defined MSDOS +#define BEYOND_STUPID 0 +#define BEYOND_TIMEOUT 2 +#define BEYOND_KINGATTACK 4 +#define BEYOND_QUESTIONABLE 6 +#define BEYOND_TESUJI 6 +#define BEYOND_DROP 8 +#else +#define BEYOND_STUPID 0 +#define BEYOND_TIMEOUT 2 +#define BEYOND_KINGATTACK 6 +#define BEYOND_QUESTIONABLE 8 +#define BEYOND_TESUJI 8 +#define BEYOND_DROP 10 +#endif + +static short MaxNum[MAXDEPTH] = + {-1,40,80,20,40,10, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + }; + +#ifdef HASHKEYTEST + extern int CheckHashKey (); + extern char mvstr[4][6]; +#endif + + +inline +static +void +GenMakeMove (short int side, + short f, + short t, + short int *tempb, /* piece at to square */ + short int *tempc, /* color of to square */ + short int promote_piece) + +/* + * Update Arrays board[] and color[] to reflect the new board + * position obtained after making the move pointed to by node. + */ + +{ + register short int piece, upiece, n; + + t = t & 0x7f; + +#ifdef DEBUG + assert(f!=NO_SQUARES); +#endif + + if (f > NO_SQUARES ) + { + piece = f - NO_SQUARES; + if ( piece > NO_PIECES ) piece -= NO_PIECES; + board[t] = piece; + color[t] = side; + n = Captured[side][piece]--; + UpdateDropHashbd (side, piece, n); + UpdateHashbd (side, piece, -1, t); + UpdatePieceList (side, t, ADD_PIECE); + } + else + { + *tempb = board[t]; + *tempc = color[t]; + if ( *tempb != no_piece ) { + n = ++Captured[side][upiece = unpromoted[*tempb]]; + UpdateDropHashbd (side, upiece, n); + UpdateHashbd (*tempc, *tempb, -1, t); + UpdatePieceList (*tempc, t, REMOVE_PIECE); + } + piece = board[f]; + Pindex[t] = Pindex[f]; + PieceList[side][Pindex[t]] = t; + color[f] = neutral; + board[f] = no_piece; + color[t] = side; + if ( promote_piece ) { + UpdateHashbd(side,piece,f,-1); + board[t] = promoted[piece]; + UpdateHashbd(side,board[t],-1,t); + } else { + board[t] = piece; + UpdateHashbd(side,piece,f,t); + } + } +#ifdef DEBUG + assert(Captured[black][0]==0 && Captured[white][0]==0); +#endif +#ifdef HASHKEYTEST + if ( CheckHashKey () ) { + algbr(f,t,0); + printf("error in GenMakeMove: %s\n",mvstr[0]); + exit(1); + } +#endif +} + +static +void +GenUnmakeMove (short int side, + short f, + short t, + short int tempb, + short int tempc, + short int promote_piece) + +/* + * Take back a move. + */ + +{ + register short piece, upiece, n; + + t = t & 0x7f; + +#ifdef DEBUG + assert(f!=NO_SQUARES); +#endif + + if (f > NO_SQUARES ) + { + piece = f - NO_SQUARES; + if ( piece > NO_PIECES ) piece -= NO_PIECES; + board[t] = no_piece; + color[t] = neutral; + n = ++Captured[side][piece]; + UpdateDropHashbd (side, piece, n); + UpdateHashbd (side, piece, -1, t); + UpdatePieceList (side, t, REMOVE_PIECE); + } + else + { + piece = board[t]; + color[t] = tempc; + board[t] = tempb; + Pindex[f] = Pindex[t]; + PieceList[side][Pindex[f]] = f; + if ( tempb != no_piece ) { + n = Captured[side][upiece=unpromoted[tempb]]--; + UpdateDropHashbd (side, upiece, n); + UpdateHashbd (tempc, tempb, -1, t); + UpdatePieceList (tempc, t, ADD_PIECE); + } + color[f] = side; + if ( promote_piece ) { + UpdateHashbd(side,piece,-1,t); + board[f] = unpromoted[piece]; + UpdateHashbd(side,board[f],f,-1); + } else { + board[f] = piece; + UpdateHashbd(side,piece,f,t); + } + } +#ifdef DEBUG + assert(Captured[black][0]==0 && Captured[white][0]==0); +#endif +#ifdef HASHKEYTEST + if ( CheckHashKey () ) { + algbr(f,t,0); + printf("error in GenUnmakeMove: %s\n",mvstr[0]); + exit(1); + } +#endif +} + + + +static void +gives_check_flag (unsigned short *flags, short side, short f, short t) +{ + short tempb, tempc, blockable, promote_piece; + promote_piece = (*flags & promote) != 0; + GenMakeMove (side, f, t, &tempb, &tempc, promote_piece); + if ( SqAtakd(sqxking, side, &blockable) ) + *flags |= check; + GenUnmakeMove (side, f, t, tempb, tempc, promote_piece); +} + + +inline +static +void +Link (short side, short piece, + short from, short to, unsigned short local_flag, short s) +{ +#ifdef notdef + if (debug_eval ) { + fprintf ( debug_eval_file, "link from %d to %d InCheck %d tsume %d\n", + from, to, InCheck, flag.tsume ); + } +#endif + + if ( *TrP == TREE ) { +#ifdef NONDSP + printf("TREE overflow\n"); +#else + ShowMessage("TREE overflow\n"); +#endif + } else { + node->f = from; + node->t = (local_flag & promote) ? (to | 0x80) : to; + node->reply = 0; + node->flags = local_flag; + node->score = s; + node->INCscore = INCscore; + if ( GenerateAllMoves ) + { + (*TrP)++, node++; + } + else if ( InCheck ) + { + /* only moves out of check */ + short tempb, tempc, sq, threat, blockable, promote_piece; + promote_piece = (node->flags & promote) != 0; + GenMakeMove (side, node->f, node->t, &tempb, &tempc, promote_piece); + sq = (from == sqking) ? to : sqking; + threat = SqAtakd(sq, side ^ 1, &blockable); + GenUnmakeMove (side, node->f, node->t, tempb, tempc, promote_piece); + if ( !threat ) + (*TrP)++, node++; + } + else if ( flag.tsume ) + { + /* only moves that give check */ + if ( !(node->flags & check) && !check_determined ) { + /* determine check flag */ + gives_check_flag(&node->flags,side,node->f,node->t); + } + if ( node->flags & check ) + (*TrP)++, node++; + } + else + (*TrP)++, node++; + } +} + + +inline +int +PromotionPossible (short int color, short int f, short int t, short int p) +{ + if ( color == black ) { + if ( f < 54 && t < 54 ) return(false); + } else { + if ( f > 26 && t > 26 ) return(false); + }; + + switch ( p ) { + case pawn: return(true); + case lance: return(true); + case knight: return(true); + case silver: return(true); + case bishop: return(true); + case rook: return(true); + }; + + return(false); +} + + +inline +int +NonPromotionPossible (short int color, short int f, short int t, short int p) +{ + switch ( p ) { + case pawn : + if ( color == black ) + return ((t < 72) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false)); + else + return ((t > 8) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false)); + case lance: + if ( color == black ) + return ((t < 72) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false)); + else + return ((t > 8) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false)); + case knight: + if ( color == black ) + return ((t < 63) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false)); + else + return ((t > 17) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false)); + }; + + return(true); +} + + +#if defined FIELDBONUS || defined DROPBONUS + +inline +static +short +field_bonus (short int ply, short int side, short int piece, short int f, short int t, + unsigned short *local_flag) + +/* bonus for possible next moves */ + +{ + register short s, u, ptyp; + register unsigned char *ppos, *pdir; + register short c1, c2; +#ifdef SAVE_NEXTPOS + short d; +#endif + + c1 = side; + c2 = side ^ 1; + + s = 0; + + check_determined = true; + + ptyp = ptype[side][piece]; + +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,t); +#else + ppos = (*nextpos[ptyp])[t]; + pdir = (*nextdir[ptyp])[t]; + u = ppos[t]; +#endif + + do + { short coloru = color[u]; + if ( piece != king && GameCnt > 40 ) { + if ( distance(u,EnemyKing) <= 1 ) { + /* can reach square near own king */ + s += 2; + *local_flag |= kingattack; + } else if ( distance(u,OwnKing) <= 1 ) { + /* can reach square near enemy king */ + s++; + *local_flag |= kingattack; + } + } + if (coloru == side ) { + /* impossible next move */ +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,t); +#else + u = pdir[u]; +#endif + } else { + /* possible next move */ + if (PromotionPossible(side,t,u,piece)) { + /* possible promotion in next move */ + if ( piece == pawn ) + { + s += 2; +#ifdef TESUJIBONUS + if ( !InPromotionZone(side,t) ) { + *local_flag |= tesuji; /* The dangling pawn */ + s++; + } +#endif + } + else + s++; + } + if (coloru == neutral) { + /* next move to an empty square */ + if ( u == FROMsquare ) { + /* opponent has just left this square */ + s++; + } +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,t,u); +#else + u = ppos[u]; +#endif + } else { + /* attack opponents piece */ +#ifdef TESUJIBONUS + short boardu, upiece, rvupiece, rvuboard; +#endif + s++; + if ( u == TOsquare ) + /* opponent has moved to TOsquare */ + s++; + if ( (boardu = board[u]) == king ) { + s += 20; INCscore -= 18; + *local_flag |= check; /* move threatens opponents king */ + } +#ifdef TESUJIBONUS + upiece = unpromoted[piece]; + rvupiece = relative_value[upiece]; + rvuboard = relative_value[unpromoted[boardu]]; + if ( upiece == pawn && Captured[side][pawn] > 1 ) + { + *local_flag |= tesuji; /* The joining pawn attack */ + s++; + } + if ( rvupiece <= rvuboard ) + { + *local_flag |= tesuji; /* The striking pawn (piece) attack */ + if ( f > NO_SQUARES ) + s += 2; + else + s++; + if ( upiece == pawn ) { + s++; + } + if ( rvupiece == rvuboard && + upiece == pawn || upiece == bishop || upiece == knight ) { + s++; /* The opposing pawn (piece) */ + if ( upiece == pawn ) + s++; + } + } +#endif +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,t); +#else + u = pdir[u]; +#endif + } + }; + } while (u != t); + + INCscore += s; + + return(s); +} + + +#endif + + + +/* inline */ void +LinkMove (short int ply, short int f, + register short int t, + unsigned short local_flag, + short int xside, + short int score_if_impossible) + +/* + * Add a move to the tree. Assign a bonus to order the moves as follows: + * 1. Principle variation 2. Capture of last moved piece 3. Other captures + * (major pieces first) 4. Killer moves 5. Tesuji drops 6. Other Moves + * 7. Other drops. 8. Non-promoting moves + * If the flag.tsume is set, assign a high bonus for checks. + */ + +{ + register short s = 0; + register short side, piece, mv; + short flag_tsume, try_link = true; + short c1, c2, ds, is_drop = f > NO_SQUARES; + unsigned long as = 0; + + flag_tsume = flag.tsume; + + c1 = side = xside ^ 1; + c2 = xside; + + /* + * Is it determined whether the move gives check ? + */ + + check_determined = ((local_flag & check) != 0); + + mv = (f << 8) | ((local_flag & promote) ? (t | 0x80) : t); + + if ( f > NO_SQUARES ) { + piece = f - NO_SQUARES; + if ( piece > NO_PIECES ) piece -= NO_PIECES; + } else { + piece = board[f]; + } + + if ( score_if_impossible < 0 ) { + /* The move is flagged as illegal. */ + Link (side, piece, + f, t, local_flag, score_if_impossible); + return; + } + + INCscore = 0; + +#ifdef HISTORY +#ifdef DEBUG + if ( use_history ) { + unsigned short hi; + short ds; + s += (ds = history[hi = hindex(side,mv)]); + } +#else + s += history[hindex(side,mv)]; +#endif +#endif + + /* If we're running short of tree node, go into tsume mode. */ + + if ( !(local_flag & capture) ) + if ( *TrP > TREE - 300 ) { + /* too close to tree table limit */ + flag.tsume = true; + } + + /* Guess strength of move and set flags. */ + + if ( piece != king && !in_opening_stage ) { + if ( distance(t,EnemyKing) <= 1 ) { + /* bonus for square near enemy king */ + s += 15; INCscore += 2; + local_flag |= kingattack; + } else if ( distance(t,OwnKing) <= 1 ) { + /* bonus for square near own king */ + s += 10; INCscore++; + local_flag |= kingattack; + } + } + + if ( tas /* own attack array available */ ) { + /* square t defended by own piece (don't count piece to move) ? */ + if ( is_drop ? (as = atak[side][t]) : (as = ((atak[side][t] & CNT_MASK) > 1)) ) + s += (ds = in_endgame_stage ? 100 : 10); + } + if ( taxs /* opponents attack array available */ ) { + /* square t not threatened by opponent or + * defended and only threatened by opponents king ? + */ + unsigned long axs; + if ( !(axs = atak[xside][t]) || + (tas && as && (axs & control[king]) && (axs & CNT_MASK) == 1) ) + s += (ds = in_endgame_stage ? 200 : + (is_drop ? (InPromotionZone(side,t) ? 40 + relative_value[piece]: 10) : 20)); + } + + /* target square near area of action */ + + if ( TOsquare >= 0 ) + s += (9-distance(TOsquare,t)); + if ( FROMsquare >= 0 ) + s += (9-distance(FROMsquare,t)) / 2; + + /* target square near own or enemy king */ + + if ( !in_opening_stage && piece != king ) { + if ( balance[c1] < 50 ) + s += (9-distance(EnemyKing,t)) * (50 - balance[c1]) / 20; + else + s += (9-distance(OwnKing,t)) * (balance[c1] - 50) / 20; + } + + if ( f > NO_SQUARES ) + { + /* bonus for drops, in order to place drops before questionable moves */ + s += in_endgame_stage ? 25 : 10; + if (t == FROMsquare) { + /* drop to the square the opponent has just left */ + s += 5; + }; + if ( piece == gold ) + s -= 32 / Captured[side][gold]; + else if ( piece == silver ) + s -= 16 / Captured[side][silver]; +#if defined DROPBONUS + s += field_bonus(ply,side,piece,f,t,&local_flag); + if ( s == 10 && piece != pawn ) + local_flag |= questionable; +#endif + } + else + { + /* bonus for moves (non-drops) */ + int consider_last = false; + if ( in_endgame_stage && Captured[side][gold] ) + s += 10; + s += 20; + if (t == FROMsquare) { + /* move to the square the opponent has just left */ + s += in_endgame_stage ? 10 : 1; + } + if (color[t] != neutral) + { + /* Captures */ + if ( in_endgame_stage ) { + s += relative_value[board[t]] - relative_value[piece]; + } else { + s += (*value)[stage][board[t]] - relative_value[piece]; + } + if (t == TOsquare) + /* Capture of last moved piece */ + s += in_endgame_stage ? 5 : 50; + } + if ( local_flag & promote ) + { + /* bonus for promotions */ + s++; + INCscore += value[stage][promoted[piece]] - value[stage][piece]; + } + else + { + /* bonus for non-promotions */ + if ( PromotionPossible(side,f,t,piece) ) +#ifdef TESUJIBONUS + /* Look at non-promoting silver or knight */ + if ( piece == silver || piece == knight ) + { + local_flag |= tesuji; /* Non-promotion */ + s++; + } + else +#endif + { + consider_last = true; + if ( piece == pawn || piece == bishop || piece == rook ) { + local_flag |= stupid; + INCscore -= 20; + } else { + local_flag |= questionable; + INCscore -= 10; + } + } + } + if ( consider_last ) + { + if ( local_flag & stupid ) + s = 0; + else + s = s % 20; + } + else + { + short blockable; +#if defined FIELDBONUS + s += field_bonus(ply,side,piece,f,t,&local_flag); +#endif + } + } + +#if defined CHECKBONUS + /* determine check flag */ + if ( !(local_flag & check) && !check_determined ) + { + gives_check_flag(&local_flag, side, f, t); + if ( local_flag & check ) + s += 20; + } +#endif + + /* check conditions for deep search cut (flag.tsume = true) */ + +#ifdef DEEPSEARCHCUT + if ( !flag.tsume && deepsearchcut ) + { + if ( ply > BEYOND_STUPID && (local_flag & stupid) ) { + try_link = flag.force || (ply == 1 && side != computer); +#ifdef HARDTIMELIMIT + } else if ( ply > BEYOND_TIMEOUT && flag.timeout ) { + flag.tsume = true; +#endif + } else if ( ply > BEYOND_KINGATTACK && !(local_flag & kingattack) ) { + flag.tsume = true; + } else if ( ply > BEYOND_QUESTIONABLE && (local_flag & questionable) ) { + flag.tsume = true; +#ifdef TESUJIBONUS + } else if ( ply > BEYOND_TESUJI && !(local_flag & tesuji) ) { + flag.tsume = true; +#endif + } else if ( ply > BEYOND_DROP && (f > NO_SQUARES) ) { + flag.tsume = true; + } + } +#endif + + if ( try_link || GenerateAllMoves ) + Link (side, piece, + f, t, local_flag, s - ((SCORE_LIMIT+1000)*2)); + + flag.tsume = flag_tsume; +} + + + +short +DropPossible (short int piece, short int side, short int sq) + +{ + short r = row(sq), possible = true; + + if ( board[sq] != no_piece ) + possible = false; + else if ( piece == pawn ) + { + if ( side == black && r == 8 ) { + possible = (generate_move_flags ? ILLEGAL_TRAPPED : false); + } else if ( side == white && r == 0 ) { + possible = (generate_move_flags ? ILLEGAL_TRAPPED : false); + } else if ( PawnCnt[side][column(sq)] ) { + possible = (generate_move_flags ? ILLEGAL_DOUBLED : false); + } + /* pawn drops are invalid, if they mate the opponent */ + if ( possible ) + { short f, tempb, tempc; + f = pawn + NO_SQUARES; + if ( side == white ) f += NO_PIECES; + GenMakeMove (side, f, sq, &tempb, &tempc, false); + if ( IsCheckmate(side^1,-1,-1) ) + possible = (generate_move_flags ? ILLEGAL_MATE : false); + GenUnmakeMove (side, f, sq, tempb, tempc, false); + } + } + else if ( piece == lance ) + { + if ( side == black && r == 8 ) + possible = (generate_move_flags ? ILLEGAL_TRAPPED : false); + else if ( side == white && r == 0 ) + possible = (generate_move_flags ? ILLEGAL_TRAPPED : false); + } + else if ( piece == knight ) + { + if ( side == black && r >= 7 ) + possible = (generate_move_flags ? ILLEGAL_TRAPPED : false); + else if ( side == white && r <= 1 ) + possible = (generate_move_flags ? ILLEGAL_TRAPPED : false); + } + + return possible; + +} + + +static +void +SortMoves(short int ply) +{ + short int p; + for (p = TrPnt[ply]; p < TrPnt[ply+1]; p++) + pick(p,TrPnt[ply+1]-1); +} + + +#ifdef DONTUSE_HEURISTIC + +static void +DontUseMoves(short int ply, short int n) +{ + register struct leaf far *p; + short int i,k; +#ifdef DEBUG + short j = 0; +#endif + /* k = number of check moves + number of captures */ + for (i = TrPnt[ply], k=0; i < TrPnt[ply+1]; i++) { + p = &Tree[i]; + if ( (p->flags & check) || (p->flags & capture) ) + if (++k >= n) return; + } + /* use n moves */ + for (i = TrPnt[ply]; i < TrPnt[ply+1]; i++) { + p = &Tree[i]; + if ( !((p->flags & check) || (p->flags & capture)) ) { + if ( k < n ) + k++; + else { + p->score = DONTUSE; +#ifdef DEBUG + j++; +#endif + } + } + } +#ifdef notdef + if ( j ) + printf("skipping %d moves at ply %d with allowed %d moves\n",j,ply,n); +#endif +} + + +#endif + + +inline +void +GenMoves (register short int ply, register short int sq, short int side, + short int xside) + +/* + * Generate moves for a piece. The moves are taken from the precalulated + * array nextpos/nextdir. If the board is free, next move is choosen from + * nextpos else from nextdir. + */ + +{ + register short u, piece, col; + short ptyp, possible; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char *ppos, *pdir; +#endif + + piece = board[sq]; + ptyp = ptype[side][piece]; + +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + + do + { unsigned short int local_flag; + short c; + if ( (c = color[u]) == xside ) + local_flag = capture; + else + local_flag = 0; + if ( c != side && board[u] != king ) { + if ( PromotionPossible(color[sq],sq,u,piece) ) { + LinkMove (ply, sq, u, local_flag | promote, xside, true); + if ( possible = NonPromotionPossible(color[sq],sq,u,piece) ) + LinkMove (ply, sq, u, local_flag, xside, possible); + } else { + LinkMove (ply, sq, u, local_flag, xside, true); + } + } + if (c == neutral) +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,sq,u); + else + u = next_direction(ptyp,&d,sq); +#else + u = ppos[u]; + else + u = pdir[u]; +#endif + } while (u != sq); +} + + + +static void +DropToSquare (short side, short xside, short ply, short u) + +/* + * Drop each piece in hand of "side" to square "u" (if allowed). + */ + +{ + short i, possible; + + for (i = pawn; i < king; i++) + if ( Captured[side][i] ) + if ( possible = DropPossible(i,side,u) ) + { short f; + f = NO_SQUARES + i; + if ( side == white ) f += NO_PIECES; + LinkMove (ply, f, u, (dropmask | i), xside, possible); + } +} + + +static void +LinkPreventCheckDrops (short side, short xside, short ply) + +/* + * Add drops of side that prevent own king from being in check + * from xside's sweeping pieces. + */ + +{ +#ifdef SAVE_NEXTPOS + short d, dd; +#else + register unsigned char *ppos, *pdir; +#endif + register short piece, u, xu, square, ptyp; + short i, n, drop_square[9]; + + if ( board[square = PieceList[side][0]] != king ) + return; + + for (piece = lance; piece <= rook; piece++ ) + if ( piece == lance || piece == bishop || piece == rook ) { + /* check for threat of xside piece */ + ptyp = ptype[side][piece]; + n = 0; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + ppos = (*nextpos[ptyp])[square]; + pdir = (*nextdir[ptyp])[square]; + u = ppos[square]; +#endif + + do + { + if (color[u] == neutral) + { +#ifdef SAVE_NEXTPOS + dd = d; + xu = next_position(ptyp,&d,square,u); + if ( xu == next_direction(ptyp,&dd,square) ) + n = 0; /* oops new direction */ + else { +#ifdef DEBUG + assert(n<9); +#endif + drop_square[n++] = u; + } +#else + if ((xu = ppos[u]) == pdir[u]) + n = 0; /* oops new direction */ + else { +#ifdef DEBUG + assert(n<9); +#endif + drop_square[n++] = u; + } +#endif + u = xu; + } + else + { + if (color[u] == xside && (unpromoted[board[u]] == piece)) + { + /* king is threatened by opponents piece */ + while ( n > 0 ) { + DropToSquare(side,xside,ply,drop_square[--n]); + } + } + else + n = 0; +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,square); +#else + u = pdir[u]; +#endif + } + } while (u != square); + + } + +} + + +static void +LinkCheckDrops (short side, short xside, short ply) + +/* + * Add drops that check enemy king. + */ + +{ +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char *ppos, *pdir; +#endif + register short u, ptyp; + short square, piece; + + if ( board[square = PieceList[xside][0]] != king ) + return; + + for (piece = pawn; piece < king; piece++) + if ( Captured[side][piece] ) { + /* + * "side" has "piece" in hand. Try to make a piece move from + * opponents king square and drop this piece to each + * reachable empty square. This definitely gives check! + * For a pawn drop it must not double pawns and + * it must not be checkmate! + */ + ptyp = ptype[xside][piece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,square); +#else + ppos = (*nextpos[ptyp])[square]; + pdir = (*nextdir[ptyp])[square]; + u = ppos[square]; +#endif + do + { + if (color[u] == neutral) + { + if ( piece != pawn || DropPossible(pawn,side,u) ) { + short f; + f = NO_SQUARES + piece; + if ( side == white ) f += NO_PIECES; + LinkMove (ply, f, u, (dropmask | piece | check), xside, true); + } +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,square,u); +#else + u = ppos[u]; +#endif + } + else + { +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,square); +#else + u = pdir[u]; +#endif + } + } while (u != square); + } + +} + + +void +MoveList (short int side, register short int ply, + short int in_check, short int blockable) + +/* + * Fill the array Tree[] with all available moves for side to play. Array + * TrPnt[ply] contains the index into Tree[] of the first move at a ply. + * in_check = 0 side is not in check + * in_check > 1 side is in check + * in_check < 0 don't know + * in_check -2 indicates move generation for book moves + */ + +{ + register short i, xside, f, u; + struct leaf far *firstnode; + short flag_tsume, num; + +#ifdef HISTORY + unsigned short hiHt=0, hi0=0, hi1=0, hi2=0, hi3=0, hi4=0; +#endif + + flag_tsume = flag.tsume; + + xside = side ^ 1; + + sqking = PieceList[side][0]; + sqxking = PieceList[xside][0]; + + if ( in_check >= 0 ) + InCheck = in_check; + else + InCheck = (board[sqking] == king) ? SqAtakd(sqking,xside, &blockable) : false; + + GenerateAllMoves = (in_check == -2) || generate_move_flags; + +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf ( debug_eval_file, "%s king is %sin check\n", + ColorStr[side],(InCheck ? "" : "not ") ); +#endif + + if ( InCheck /* && (ply > 1 || side == computer) */ ) + { + /* Own king in check */ + flag.tsume = true; + } + + TrP = &TrPnt[ply + 1]; + *TrP = TrPnt[ply]; + + firstnode = node = &Tree[*TrP]; + + if (!PV) + Swag0 = killr0[ply]; + else Swag0 = PV; + Swag1 = killr1[ply]; + Swag2 = killr2[ply]; + Swag3 = killr3[ply]; + if (ply > 2) + Swag4 = killr1[ply - 2]; else Swag4 = 0; + +#ifdef DEBUG_EVAL + if ( debug_eval && (ply == 1 || debug_moves) ) + { + char bufHt[8], buf0[8], buf1[8], buf2[8], buf3[8], buf4[8]; + movealgbr(SwagHt,bufHt); + movealgbr(Swag0,buf0); + movealgbr(Swag1,buf1); + movealgbr(Swag2,buf2); + movealgbr(Swag3,buf3); + movealgbr(Swag4,buf4); + fprintf(debug_eval_file, "SwagHt=%x %s 0=%x %s 1=%x %s 2=%x %s 3=%x %s 4=%x %s\n", + SwagHt, bufHt, Swag0, buf0, Swag1, buf1, Swag2, buf2, Swag3, buf3, Swag4, buf4); + } +#endif + +#ifdef HISTORY + if ( use_history ) { + history[hiHt = hindex(side,SwagHt)] += 5000; + history[hi0 = hindex(side,Swag0)] += 2000; + history[hi1 = hindex(side,Swag1)] += 60; + history[hi2 = hindex(side,Swag2)] += 50; + history[hi3 = hindex(side,Swag3)] += 40; + history[hi4 = hindex(side,Swag4)] += 30; + } +#endif + + if ( tas = MatchSignature(threats_signature[side]) ) { +#if defined notdef && defined DEBUG_EVAL && defined NONDSP + printf("threats available at ply %d for side=%s\n",ply,ColorStr[side]); +#endif + } + if ( taxs = MatchSignature(threats_signature[xside]) ) { +#if defined notdef && defined DEBUG_EVAL && defined NONDSP + printf("threats available at ply %d for xside=%s\n",ply,ColorStr[xside]); +#endif + } + if ( ssa = MatchSignature(squares_signature) ) { +#if defined notdef && defined DEBUG_EVAL && defined NONDSP + printf("square statistics available at ply %d\n",ply); +#endif + } + + for (i = PieceCnt[side]; i >= 0; i--) + GenMoves (ply, PieceList[side][i], side, xside); + + if ( !InCheck || blockable ) + if ( flag.tsume ) + { /* special drop routine for tsume problems */ + if ( InCheck ) { + LinkPreventCheckDrops (side, xside, ply); + } else { + LinkCheckDrops (side, xside, ply); + } + + } + else + { + for ( u = 0; u < NO_SQUARES; u++ ) + DropToSquare(side,xside,ply,u); + } + +#ifdef HISTORY + if ( use_history ) { + history[hiHt] -= 5000; + history[hi0] -= 2000; + history[hi1] -= 60; + history[hi2] -= 50; + history[hi3] -= 40; + history[hi4] -= 30; + } +#endif + + SwagHt = 0; /* SwagHt is only used once */ + + if ( flag.tsume && node == firstnode ) + (*TrP)++; + + GenCnt += (num = (TrPnt[ply+1] - TrPnt[ply])); + +#ifdef DEBUG_EVAL + SortMoves(ply); +#endif + +#ifdef DONTUSE_HEURISTIC + /* remove some nodes in case of wide spread in depth */ + if ( !flag.tsume && (i = MaxNum[ply]) > 0 && num > i) { + SortMoves(ply); + DontUseMoves(ply,i); + } +#endif + +#ifdef notdef + printf("%d moves at ply %d\n",num,ply); +#endif + + flag.tsume = flag_tsume; + +} + +void +CaptureList (register short int side, short int ply, + short int in_check, short int blockable) + +/* + * Fill the array Tree[] with all available captures for side to play. + * If there is a non-promote option, discard the non-promoting move. + * Array TrPnt[ply] contains the index into Tree[] of the first move + * at a ply. + * If flag.tsume is set, only add captures (but also the non-promoting) + * that threaten the opponents king. + * in_check = 0 side is not in check + * in_check > 1 side is in check + * in_check < 0 don't know + */ + +{ + register short u, sq, xside; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char *ppos, *pdir; +#endif + short i, piece, flag_tsume; + small_short *PL; + + xside = side ^ 1; + + TrP = &TrPnt[ply + 1]; + *TrP = TrPnt[ply]; + node = &Tree[*TrP]; + + flag_tsume = flag.tsume; + + sqking = PieceList[side][0]; + sqxking = PieceList[xside][0]; + + if ( in_check >= 0 ) + InCheck = in_check; + else + InCheck = (board[sqking] == king) ? SqAtakd(sqking,xside,&blockable) : false; + + GenerateAllMoves = (in_check == -2); + +#ifdef DEBUG_EVAL + if (debug_eval ) + fprintf ( debug_eval_file, "%s king is %sin check\n", + ColorStr[side],(InCheck ? "" : "not ") ); +#endif + + if ( InCheck && (ply > 1 || side == computer) ) + { + /* Own king is in check */ + flag.tsume = true; + } + + check_determined = false; + + PL = PieceList[side]; + + for (i = 0; i <= PieceCnt[side]; i++) + { short ptyp; + sq = PL[i]; + piece = board[sq]; + ptyp = ptype[side][piece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + do + { + if (color[u] == neutral) + { +#ifdef SAVE_NEXTPOS + u = next_position(ptyp,&d,sq,u); +#else + u = ppos[u]; +#endif + } + else + { + if ( color[u] == xside && board[u] != king ) + { + short PP; + if ( PP = PromotionPossible(color[sq],sq,u,piece) ) { + Link (side, piece, + sq, u, capture | promote, + (*value)[stage][board[u]] +#if !defined SAVE_SVALUE + + svalue[board[u]] +#endif + - relative_value[piece]); + } + if ( !PP || flag.tsume ) { + Link (side, piece, + sq, u, capture, + (*value)[stage][board[u]] +#if !defined SAVE_SVALUE + + svalue[board[u]] +#endif + - relative_value[piece]); + } + } +#ifdef SAVE_NEXTPOS + u = next_direction(ptyp,&d,sq); +#else + u = pdir[u]; +#endif + } + } while (u != sq); + } + + flag.tsume = flag_tsume; + + SwagHt = 0; /* SwagHt is only used once */ + +#ifdef DEBUG_EVAL + SortMoves(ply); +#endif + +} + + + +short +IsCheckmate (short int side, short int in_check, short int blockable) + +/* + * If the king is in check, try to find a move that prevents check. + * If such a move is found, return false, otherwise return true. + * in_check = 0: side is not in check + * in_check > 1: side is in check + * in_check < 0: don't know + * blockable > 0 && check: check can possibly prevented by a drop + * blockable = 0 && check: check can definitely not prevented by a drop + * blockable < 0 && check: nothing known about type of check + */ + +{ + register short u, sq, xside; +#ifdef SAVE_NEXTPOS + short d; +#else + register unsigned char *ppos, *pdir; +#endif + short i, piece, flag_tsume; + small_short *PL; + struct leaf far *firstnode; + short tempb, tempc, ksq, threat, dummy, sqking; + short InCheck; + + xside = side ^ 1; + + sqking = PieceList[side][0]; + + /* + * Checkmate is possible only if king is in check. + */ + + if ( in_check >= 0 ) + InCheck = in_check; + else if ( board[sqking] == king ) + InCheck = SqAtakd(sqking,xside,&blockable); + else + InCheck = false; + + if ( !InCheck ) + return (false); + + /* + * Try to find a move, that prevents check. + */ + + PL = PieceList[side]; + + for (i = 0; i <= PieceCnt[side]; i++) + { short ptyp; + sq = PL[i]; + piece = board[sq]; + ptyp = ptype[side][piece]; +#ifdef SAVE_NEXTPOS + u = first_direction(ptyp,&d,sq); +#else + ppos = (*nextpos[ptyp])[sq]; + pdir = (*nextdir[ptyp])[sq]; + u = ppos[sq]; +#endif + do + { + if (color[u] == neutral || color[u] == xside) + { + GenMakeMove (side, sq, u, &tempb, &tempc, false); + ksq = (sq == sqking) ? u : sqking; + threat = SqAtakd(ksq,xside,&dummy); + GenUnmakeMove (side, sq, u, tempb, tempc, false); + if ( !threat ) + return (false); + } +#ifdef SAVE_NEXTPOS + u = (color[u] == neutral) ? next_position(ptyp,&d,sq,u) + : next_direction(ptyp,&d,sq); +#else + u = (color[u] == neutral) ? ppos[u] : pdir[u]; +#endif + } while (u != sq); + } + + /* + * Couldn't find a move that prevents check. + * Try to find a drop, that prevents check. + */ + + if ( blockable != 0 ) + { + for (piece = king-1; piece >= pawn; piece--) + if ( Captured[side][piece] ) + { + for (u = 0; u < NO_SQUARES; u++) + if ( DropPossible(piece,side,u) ) + { short f; + f = NO_SQUARES + piece; + if ( side == white ) f += NO_PIECES; + GenMakeMove (side, f, u, &tempb, &tempc, false); + threat = SqAtakd(sqking,xside,&dummy); + GenUnmakeMove (side, f, u, tempb, tempc, false); + if ( !threat ) + return (false); + } + /* + * If the piece could be dropped at any square, it is + * impossible for any other piece drop to prevent check. + * Drops are restricted for pawns, lances, and knights. + */ + if ( piece > knight ) + break; + } + } + + return (true); + +} + + diff --git a/src/globals.c b/src/globals.c new file mode 100644 index 0000000..c23d9f7 --- /dev/null +++ b/src/globals.c @@ -0,0 +1,176 @@ +/* + * globals.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" + + +short int ahead = true, hash = true; +char far *xwin = 0; +char far *Lang = NULL; + + +short FROMsquare, TOsquare; + +small_short ChkFlag[MAXDEPTH], CptrFlag[MAXDEPTH], TesujiFlag[MAXDEPTH]; +short Pscore[MAXDEPTH], Tscore[MAXDEPTH]; +small_short Pindex[NO_SQUARES]; + +short mtl[2], hung[2]; +small_short PieceCnt[2]; + +char ColorStr[2][10]; + +long znodes; + + + +#ifdef BINBOOK +extern char *binbookfile; +#endif +extern char *bookfile; + +unsigned long hashkey, hashbd; + +char savefile[128]; +char listfile[128]; + +short rpthash[2][256]; +short TrPnt[MAXDEPTH]; +small_short PieceList[2][NO_SQUARES]; +small_short PawnCnt[2][NO_COLS]; +small_short Captured[2][NO_PIECES]; +small_short Mvboard[NO_SQUARES]; +#if !defined SAVE_SVALUE +short svalue[NO_SQUARES]; +#endif +struct flags flag; + +short opponent, computer, WAwindow, WBwindow, BAwindow, BBwindow, dither, + INCscore; +long ResponseTime=0, ExtraTime=0, MaxResponseTime=0, et=0, et0=0, time0=0, ft=0; +#ifdef INTERRUPT_TEST +long it, itime0; +#endif +long GenCnt, NodeCnt, ETnodes, EvalNodes, HashCnt, HashAdd, FHashCnt, FHashAdd, + HashCol, THashCol, filesz, hashmask, hashbase; +long replus, reminus; +short HashDepth = HASHDEPTH, HashMoveLimit = HASHMOVELIMIT; +short player, xwndw; +short rehash = -1; +short Sdepth, Game50, MaxSearchDepth; +short GameCnt = 0; +short contempt; +int Book; +struct TimeControlRec TimeControl; +int TCadd = 0; +short TCflag, TCmoves, TCminutes, TCseconds, OperatorTime; +short XCmoves[3]={0,0,0}; +short XCminutes[3]={0,0,0}; +short XCseconds[3]={0,0,0}; +short XC=0, XCmore=0; +const short otherside[3] = +{white, black, neutral}; +unsigned short hint; +short int TOflag; /* force search re-init if we backup search */ + +unsigned short killr0[MAXDEPTH], killr1[MAXDEPTH]; +unsigned short killr2[MAXDEPTH], killr3[MAXDEPTH]; +unsigned short PV, SwagHt, Swag0, Swag1, Swag2, Swag3, Swag4, sidebit; + +small_short HasPiece[2][NO_PIECES]; + +const short kingP[3] = +{4, 76, 0}; + +const small_short relative_value[NO_PIECES] = +{0, 1, 3, 4, 7, 9, 10, 12, + 2, 5, 6, 8, 11, 13, 14}; + +const long control[NO_PIECES] = +{0, ctlP, ctlL, ctlN, ctlS, ctlG, ctlB, ctlR, + ctlPp, ctlLp, ctlNp, ctlSp, ctlBp, ctlRp, ctlK }; + +short stage, stage2; +short balance[2]; + +#ifdef HASHFILE +FILE *hashfile; +#endif + +unsigned int starttime; + +int timeopp[MINGAMEIN], timecomp[MINGAMEIN]; +int compptr, oppptr; + + +struct leaf far *Tree = NULL; + +hashcode_array far *hashcode = NULL; +drop_hashcode_array far *drop_hashcode = NULL; + +struct leaf far *root = NULL; + +struct GameRec far *GameList = NULL; + +value_array far *value = NULL; +fscore_array far *fscore = NULL; + +#ifndef SAVE_DISTDATA +short use_distdata = true; +distdata_array far *distdata = NULL; +#endif + +#ifndef SAVE_PTYPE_DISTDATA +short use_ptype_distdata = true; +distdata_array far *ptype_distdata[NO_PTYPE_PIECES]; +#endif + +#if !defined SAVE_NEXTPOS +next_array far *nextdir[NO_PTYPE_PIECES]; +next_array far *nextpos[NO_PTYPE_PIECES]; +short use_nextpos = true; +#endif + +#if defined HISTORY +short use_history = true; +unsigned short far *history = NULL; +#endif + +#ifdef CACHE +short use_etable = true; +etable_field far *etab[2] = {NULL,NULL}; +#endif + +#if ttblsz +short use_ttable = true; +unsigned int ttblsize = ttblsz; +struct hashentry far *ttable[2] = {NULL,NULL}; +#endif + + + + diff --git a/src/gnushogi.h b/src/gnushogi.h new file mode 100644 index 0000000..cf581a9 --- /dev/null +++ b/src/gnushogi.h @@ -0,0 +1,1155 @@ +/* + * gnushogi.h - Header file for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + + +#if defined THINK_C + +/* OPT */ +/* #define XSHOGI */ +/* #define BAREBONES */ +#define SMALL_MEMORY +#define SLOW_CPU +/* #define SAVE_SSCORE */ +#if !defined EXTRA_2MB +#define SAVE_PTYPE_DISTDATA +/* #define SAVE_DISTDATA */ +#define SAVE_NEXTPOS +#endif +#define HARDTIMELIMIT +#define DEEPSEARCHCUT +#define NULLMOVE +#define VERYBUGGY +#define QUIETBACKGROUND +/* #define HASGETTIMEOFDAY */ +/* #define clocktime() (100l * clock() / CLOCKS_PER_SEC) */ +#define clocktime() (100l * time(0)) +#if defined NOTABLES +#define NOTTABLE +#else +#if !defined DEBUG_TTABLE +#define HISTORY +/* #define EXACTHISTORY */ +#define CACHE +#endif +/* #define NOTTABLE */ +#endif +#define SEMIQUIETBOOKGEN +/* GENOPT */ +#define CHECKBONUS +/* #define DROPBONUS */ +/* #define FIELDBONUS */ +/* #define TESUJIBONUS */ +#define EASY_OPENINGS +/* FILES */ +#define LANGFILE "gnushogi.lng" +#define BOOK "gnushogi.tbk" +#define BINBOOK "gnushogi.bbk" +/* #define HASHFILE "gnushogi.hsh" */ +#define PATTERNFILE "gnushogi.pat" +/* #define DEBUG */ + +#define NOBYTEOPS +#include + +#define small_short char +#define small_ushort unsigned char + +#elif defined(MSDOS) && !defined(__GO32__) + +/* OPT */ +/* #define XSHOGI */ +/* #define BAREBONES */ +#define SMALL_MEMORY +#define SLOW_CPU +/* #define SAVE_SSCORE */ +#define SAVE_PTYPE_DISTDATA +/* #define SAVE_DISTDATA */ +#define SAVE_NEXTPOS +#define HARDTIMELIMIT +#define DEEPSEARCHCUT +#define NULLMOVE +#define VERYBUGGY +/* #define QUIETBACKGROUND */ +/* #define HASGETTIMEOFDAY */ +#define clocktime() (100l * time(0)) +#define HISTORY +/* #define EXACTHISTORY */ +#define CACHE +#define SEMIQUIETBOOKGEN +/* #define NOTTABLE */ +/* GENOPT */ +#define CHECKBONUS +/* #define DROPBONUS */ +/* #define FIELDBONUS */ +/* #define TESUJIBONUS */ +#define EASY_OPENINGS +/* FILES */ +#define LANGFILE "gnushogi.lng" +#define BOOK "gnushogi.tbk" +#define BINBOOK "gnushogi.bbk" +/* #define HASHFILE "gnushogi.hsh" */ +#define PATTERNFILE "gnushogi.pat" +/* #define DEBUG */ + +#define NOBYTEOPS +/* #define NOMEMOPS */ +/* #include */ + +#define small_short char +#define small_ushort unsigned char + +#else + +#ifdef __STDC__ +#define small_short signed char +#else +/* + * type small_short must cover -128..127. In case of trouble, + * try to uncommend "signed". If this doesn't help, use short. + */ +#ifdef CHAR_IS_SIGNED +#define small_short char +#else +#define small_short short +#endif +#endif + +#define small_ushort unsigned char + +#endif + + +typedef small_short BYTE; +typedef small_ushort UBYTE; +typedef short SHORT; +typedef unsigned short USHORT; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; + + +#if defined(MSDOS) && !defined(__GO32__) +#define HEAP_ALLOC(n) _fmalloc(n) +#define HEAP_FREE(p) _ffree(p) +#else +#define far +#define HEAP_ALLOC(n) malloc(n) +#define HEAP_FREE(p) free(p) +#endif + + + + +#if defined NOBYTEOPS && defined NOMEMOPS +#define array_copy(src,dst,len) \ + { long i; char far *psrc=(char far *)src, *pdst=(char far *)dst;\ + for (i=len; i; pdst[--i] = psrc[i]);\ + } +#define array_zero(dst,len) \ + { long i; char far *pdst=(char far *)dst;\ + for (i=len; i; pdst[--i] = 0);\ + } +#elif defined NOBYTEOPS +#ifdef MSDOS +#define array_copy(src,dst,len) _fmemcpy(dst,src,len) +#define array_zero(dst,len) _fmemset(dst,0,len) +#else +#define array_copy(src,dst,len) memcpy(dst,src,len) +#define array_zero(dst,len) memset(dst,0,len) +#endif +#else +#define array_copy(src,dst,len) bcopy(src,dst,len) +#define array_zero(dst,len) bzero(dst,len) +#endif + + +#if !defined(__STDC__) && !defined(MSDOS) +#define const +#endif + +#ifndef __GNUC__ +#define inline +#endif + +#include + +#ifdef BINBOOK +extern char *binbookfile; +#endif +extern char *bookfile; +extern short int ahead; +extern char far *xwin; +extern char far *Lang; + + + +#define SEEK_SET 0 +#define SEEK_END 2 +#if defined DEBUG || defined DEBUG_EVAL + extern void ShowDBLine (char *, short int, short int, + short int, short int, short int, + short unsigned int *); + extern FILE *debugfd; + extern short int debuglevel; + + extern void debug_position (FILE *D); + extern void debug_ataks (FILE *D, long *atk); +#endif /* DEBUG */ + +#include +#if !defined NO_STRING_INCLUDE +#include +#endif +#include + +#ifdef THINK_C +#define RWA_ACC "r+b" +#define WA_ACC "w+b" +#elif defined(MSDOS) && !defined(__GO32__) +#include +#include +#define malloc(size) farmalloc(size) +#define RWA_ACC "r+b" +#define WA_ACC "w+b" +#ifdef timeout +#undef timeout +#endif +#define printz printf +#define scanz scanf +#else +#define RWA_ACC "r+" +#define WA_ACC "w+" +#include +#include +#include +#endif /* MSDOS */ +#if defined NONDSP || defined THINK_C || defined MSDOS +#define printz printf +#define scanz scanf +#else +#include +#define scanz fflush(stdout),scanw +#define printz printw +#endif + +#ifdef notdef +#if defined(__STDC__) || defined(MSDOS) +/* */ + extern int fclose (FILE *); +#ifndef __ultrix /* work around bug in c89 compiler --t.mann */ + extern int fscanf (FILE *, const char *, ...); + extern int fprintf (FILE *, const char *, ...); +#endif /*__ultrix*/ + extern int fflush (FILE *); + +/* */ + extern int abs (int); + extern int atoi (const char *); + +/* */ + extern long int time (long int *); + +/* */ + extern void *memset (void *, int, size_t); +#endif +#endif + +#define NO_PIECES 15 +#define MAX_CAPTURED 19 +#define NO_PTYPE_PIECES 15 +#define NO_SQUARES 81 +#define NO_SQUARES_1 80 +#define NO_COLS 9 +#define NO_ROWS 9 + +#if defined DEBUG || defined HASHFILE || defined CACHE +#define PTBLBDSIZE (NO_SQUARES+NO_PIECES) +#endif + +#include "eval.h" + +#define SCORE_LIMIT 12000 + +/* masks into upper 16 bits of ataks array */ +/* observe order of relative piece values */ +#define CNT_MASK 0x000000FF +#define ctlP 0x00200000 +#define ctlPp 0x00100000 +#define ctlL 0x00080000 +#define ctlN 0x00040000 +#define ctlLp 0x00020000 +#define ctlNp 0x00010000 +#define ctlS 0x00008000 +#define ctlSp 0x00004000 +#define ctlG 0x00002000 +#define ctlB 0x00001000 +#define ctlBp 0x00000800 +#define ctlR 0x00000400 +#define ctlRp 0x00000200 +#define ctlK 0x00000100 + +/* attack functions */ +#define Patak(c, u) (atak[c][u] > ctlP) +#define Anyatak(c, u) (atak[c][u] != 0) + +/* hashtable flags */ +#define truescore 0x0001 +#define lowerbound 0x0002 +#define upperbound 0x0004 +#define kingcastle 0x0008 +#define queencastle 0x0010 +#define evalflag 0x0020 + +/* king positions */ +#define BlackKing PieceList[black][0] +#define WhiteKing PieceList[white][0] +#define OwnKing PieceList[c1][0] +#define EnemyKing PieceList[c2][0] + + +/* board properties */ +#define InBlackCamp(sq) ((sq) < 27) +#define InWhiteCamp(sq) ((sq) > 53) +#define InPromotionZone(side,sq) (((side)==black)?InWhiteCamp(sq):InBlackCamp(sq)) + +/* constants */ + +#define OPENING_HINT 0x141d /* P7g-7f (20->29) */ + +/* truth values */ +#define false 0 +#define true 1 + +/* colors */ +#define black 0 +#define white 1 +#define neutral 2 + +/* piece code defines */ +#define no_piece 0 +#define pawn 1 +#define lance 2 +#define knight 3 +#define silver 4 +#define gold 5 +#define bishop 6 +#define rook 7 +#define ppawn 8 +#define plance 9 +#define pknight 10 +#define psilver 11 +#define pbishop 12 +#define prook 13 +#define king 14 + +#define ptype_no_piece 0 +#define ptype_pawn 0 +#define ptype_lance 1 +#define ptype_knight 2 +#define ptype_silver 3 +#define ptype_gold 4 +#define ptype_bishop 5 +#define ptype_rook 6 +#define ptype_pbishop 7 +#define ptype_prook 8 +#define ptype_king 9 +#define ptype_wpawn 10 +#define ptype_wlance 11 +#define ptype_wknight 12 +#define ptype_wsilver 13 +#define ptype_wgold 14 + +/* node flags */ +#define pmask 0x000f /* 15 */ +#define promote 0x0010 /* 16 */ +#define dropmask 0x0020 /* 32 */ +#define exact 0x0040 /* 64 */ +#define tesuji 0x0080 /* 128 */ +#define check 0x0100 /* 256 */ +#define capture 0x0200 /* 512 */ +#define draw 0x0400 /* 1024 */ +#define stupid 0x0800 /* 2048 */ +#define questionable 0x1000 /* 4096 */ +#define kingattack 0x2000 /* 8192 */ +#define book 0x4000 /* 16384 */ + +/* move quality flags */ +#define goodmove tesuji +#define badmove stupid +#ifdef EASY_OPENINGS +#define difficult questionable +#endif + +/* move symbols */ +#define pxx (CP[2]) +#define qxx (CP[1]) +#define rxx (CP[4]) +#define cxx (CP[3]) +/***************************************************************************/ +/***************** Table limits ********************************************/ +/* + * ttblsz must be a power of 2. Setting ttblsz 0 removes the transposition + * tables. + */ +#if defined NOTTABLE +#define vttblsz 0 +#elif defined SMALL_MEMORY +#if defined SAVE_SSCORE +#define vttblsz (1 << 12) +#else +#if defined EXTRA_2MB +#define vttblsz (1 << 12) +#else +#define vttblsz (1 << 10) +#endif +#endif +#else +#ifdef DEBUG +#define vttblsz (8001) +#else /* !DEBUG */ +#define vttblsz (100001) +#endif +#endif + +#if defined SMALL_MEMORY +#define MINTTABLE (0) +#else +#ifdef DEBUG +#define MINTTABLE (2000) /* min ttable size -1 */ +#else +#define MINTTABLE (8000) /* min ttable size -1 */ +#endif +#endif + +#define ttblsz vttblsz + +#if defined SMALL_MEMORY +#if !defined SAVE_SSCORE +#define TREE 1500 /* max number of tree entries */ +#else +#define TREE 2500 /* max number of tree entries */ +#endif +#else +#define TREE 4000 /* max number of tree entries */ +#endif + +#define MAXDEPTH 40 /* max depth a search can be carried */ +#define MINDEPTH 2 /* min search depth =1 (no hint), >1 hint */ +#define MAXMOVES 300 /* max number of half moves in a game */ +#define CPSIZE 235 /* size of lang file max */ +#if defined THINK_C || defined(MSDOS) && !defined(__GO32__) || defined SMALL_MEMORY +#if defined SAVE_SSCORE +#define ETABLE (1<<10) /* static eval cache */ +#else +#if defined EXTRA_2MB +#define ETABLE (1<<10) /* static eval cache */ +#else +#define ETABLE (1<<8) /* static eval cache */ +#endif +#endif +#else +#ifdef DEBUG +#define ETABLE (1001) +#else +#define ETABLE (10001) /* static eval cache */ +#endif +#endif +/***************** tuning paramaters **********************************************/ +#if defined VERY_SLOW_CPU +#define MINRESPONSETIME 300 +#elif defined SLOW_CPU +#define MINRESPONSETIME 200 +#else +#define MINRESPONSETIME 100 /* 1 s */ +#endif +#define MINGAMEIN 4 +#define MINMOVES 15 +#define CHKDEPTH 1 /* always look forward CHKDEPTH half-moves if in check */ +#if defined SLOW_CPU || defined VERY_SLOW_CPU +#define DEPTHBEYOND 7 /* Max to go beyond Sdepth */ +#else +#define DEPTHBEYOND 11 /* Max to go beyond Sdepth */ +#endif +#define HASHDEPTH 4 /* depth above which to use HashFile */ +#define HASHMOVELIMIT 40 /* Use HashFile only for this many moves */ +#define PTVALUE 0 /* material value below which pawn threats at 5 & 3 are used */ +#define ZDEPTH 3 /* depth beyond which to check ZDELTA for extra time */ +#define ZDELTA 10 /* score delta per ply to cause extra time to be given */ +#define BESTDELTA 90 +/* about 1/2 second worth of nodes for your machine */ +#if defined VERY_SLOW_CPU +#define ZNODES (flag.tsume ? 20 : 50) /* check the time every ZNODES positions */ +#elif defined SLOW_CPU +#define ZNODES (flag.tsume ? 40 : 100) /* check the time every ZNODES positions */ +#else +#define ZNODES (flag.tsume ? 400 : 1000) /* check the time every ZNODES positions */ +#endif +#define MAXTCCOUNTX 10 /* max number of time clicks per search to complete ply */ +#define MAXTCCOUNTR 4 /* max number of time clicks per search extensions*/ +#define SCORESPLIM 8 /* Score space doesn't apply after this stage */ +#define SDEPTHLIM (Sdepth+1) +#define HISTORYLIM 4096 /* Max value of history killer */ +#ifdef EXACTHISTORY +#if defined SMALL_MEMORY +#define HISTORY_MASK 0x8000 /* mask to MSB of history index */ +#define HISTORY_SIZE 0x10000 /* size of history table */ +#else +#define HISTORY_MASK (1 << 15) /* mask to MSB of history index */ +#define HISTORY_SIZE (1 << 16) /* size of history table */ +#endif +#else +/* smaller history table, but dangerous because of collisions */ +#define HISTORY_MASK 0x3fff /* mask to significant bits of history index */ +#if defined SMALL_MEMORY +#define HISTORY_SIZE 0x4000 /* size of history table */ +#else +#define HISTORY_SIZE (1 << 14) /* size of history table */ +#endif +#endif + +#define sizeof_history (sizeof(unsigned short) * (size_t)HISTORY_SIZE) + +#ifdef EXACTHISTORY +/* Map from.to (8bit.8bit) to from.to (0.7bit.8bit) */ +#define khmove(mv) (mv & 0x7fff) +#define hmove(mv) ((mv & 0x7fff) ^ 0x5555) +#else +/* Map from.to (8bit.8bit) to from.to (00.7bit.7bit) */ +/* Swap bits of ToSquare in case of promotions, hoping that + no catastrophic collision occur. */ +#define khmove(mv) (((mv & 0x7f00) >> 1) | \ + ((mv & 0x0080) ? ((mv & 0x007f) ^ 0x007f) : (mv & 0x007f))) +#define hmove(mv) (khmove(mv) ^ 0x2aaa) +#endif + +/* mask color to 15th bit */ +#ifdef EXACTHISTORY +#define hindex(c,mv) ((c ? HISTORY_MASK : 0) | hmove(mv)) +#else +/* for white, swap bits, hoping that no catastrophic collision occur. */ +#define hindex(c,mv) (c ? ((~hmove(mv)) & HISTORY_MASK) : hmove(mv)) +#endif + +#define EWNDW 10 /* Eval window to force position scoring at depth greater than Sdepth + 2 */ +#define WAWNDW 90 /* alpha window when computer black*/ +#define WBWNDW 90 /* beta window when computer black*/ +#define BAWNDW 90 /* alpha window when computer white*/ +#define BBWNDW 90 /* beta window when computer white*/ +#define BXWNDW 90 /* window to force position scoring at lower */ +#define WXWNDW 90 /* window to force position scoring at lower */ + +#define DITHER 5 /* max amount random can alter a pos value */ +#define LBONUS 1 /* points per stage value of L increases */ +#define BBONUS 2 /* points per stage value of B increases */ +#define RBONUS 2 /* points per stage value of R increases */ + +#define QUESTIONABLE (valueK) /* malus for questionable moves */ + +#if defined STUPID +#undef STUPID +#endif + +#define STUPID (valueR<<1) /* malus for stupid moves */ + +#define KINGPOSLIMIT ( -1) /* King positional scoring limit */ +#define KINGSAFETY 32 +#define MAXrehash (7) + +/************************* parameters for Opening Book *********************************/ +#define BOOKSIZE 8000 /* Number of unique position/move combinations allowed */ +#define BOOKMAXPLY 40 /* Max plys to keep in book database */ +#define BOOKFAIL (BOOKMAXPLY/2) /* if no book move found for BOOKFAIL turns stop using book */ +#define BOOKPOCKET 64 +#define BOOKRAND 1000 /* used to select an opening move from a list */ +#define BOOKENDPCT 950 /* 5 % chance a BOOKEND will stop the book */ +#define DONTUSE -32760 /* flag move as don't use */ +#define ILLEGAL_TRAPPED -32761 /* flag move as illegal: no move from this square */ +#define ILLEGAL_DOUBLED -32762 /* flag move as illegal: two pawns on one column */ +#define ILLEGAL_MATE -32763 /* flag move as illegal: pawn drop with mate */ +/****************************************************************************************/ + struct hashval + { + unsigned long key, bd; + }; + struct hashentry + { + unsigned long hashbd; + unsigned short mv; + unsigned char depth; /* unsigned char saves some space */ + unsigned char flags; +#ifdef notdef + unsigned short age; +#endif + short score; +#ifdef HASHTEST + unsigned char bd[PTBLBDSIZE]; +#endif /* HASHTEST */ + + }; + +#if defined HASHFILE || defined CACHE + struct etable + { + unsigned long ehashbd; + short int escore[2]; +#if !defined SAVE_SSCORE + short int sscore[NO_SQUARES]; +#endif + short int score; + small_short hung[2]; +#ifdef CACHETEST + unsigned char bd[PTBLBDSIZE]; +#endif /* CACHETEST */ + } ; + +#if defined CACHE +extern short use_etable; +typedef struct etable etable_field[ETABLE]; +extern etable_field far *etab[2]; +#endif + +/* + * persistent transposition table. By default, the size is (1 << vfilesz). If you + * change the size, be sure to run gnuchess -c [vfilesz] before anything else. + */ +#define frehash 6 +#if defined SMALL_MEMORY +#define vfilesz 10 +#else +#define vfilesz 14 +#endif + struct fileentry + { + unsigned char bd[PTBLBDSIZE]; + unsigned char f, t, flags, depth, sh, sl; + }; + +#endif /* HASHFILE */ + + + struct leaf + { + small_ushort f, t; + short score, reply, width; + short INCscore; + unsigned short flags; + }; + struct GameRec + { + unsigned short gmove; /* this move */ + short score; /* score after this move */ + short depth; /* search depth this move */ + long time; /* search time this move */ + short fpiece; /* moved or dropped piece */ + short piece; /* piece captured */ + short color; /* color */ + short flags; /* move flags capture, promote, castle */ + short Game50; /* flag for repetition */ + long nodes; /* nodes searched for this move */ + unsigned long hashkey, hashbd; /* board key before this move */ +#ifdef DEBUG40 + int d1; + int d2; + int d3; + int d4; + int d5; + int d6; + int d7; +#endif + }; + struct TimeControlRec + { + short moves[2]; + long clock[2]; + }; + + struct flags + { + short mate; /* the game is over */ + short post; /* show principle variation */ + short quit; /* quit/exit */ + short regularstart; /* did the game start from standard + * initial board ? */ + short reverse; /* reverse board display */ + short bothsides; /* computer plays both sides */ + short hash; /* enable/disable transposition table */ + short force; /* enter moves */ + short easy; /* disable thinking on opponents time */ + short beep; /* enable/disable beep */ + short timeout; /* time to make a move */ + short musttimeout; /* time to make a move */ + short back; /* time to make a move */ + short rcptr; /* enable/disable recapture heuristics */ + short rv; /* reverse video */ + short stars; /* add stars to uxdsp screen */ + short coords; /* add coords to visual screen */ + short shade; + short material; /* draw on lack of material */ + short illegal; /* illegal position */ + short onemove; /* timing is onemove */ + short gamein; /* timing is gamein */ + short tsume; /* first consider checks */ + }; + + extern FILE *debugfile; + +#ifndef EVALFILE +#ifdef THINK_C +#define EVALFILE "EVAL" +#else +#define EVALFILE "/tmp/EVAL" +#endif +#endif + +extern FILE *debug_eval_file; +extern short debug_eval; +extern short debug_moves; + + +#ifdef HISTORY + extern short use_history; + extern unsigned short far *history; +#endif + extern long znodes; + + extern char ColorStr[2][10]; +#ifdef DEBUG_EVAL + extern char *PieceStr[NO_PIECES]; +#endif + extern char mvstr[4][6]; + extern unsigned short int MV[MAXDEPTH]; + extern int MSCORE; + extern int mycnt1, mycnt2; + extern short int ahead; + extern short int xshogi; + extern struct leaf rootnode; + extern struct leaf far *Tree; + extern struct leaf far *root; + extern char savefile[], listfile[]; + extern short TrPnt[]; + extern small_short board[], color[]; + extern const small_short sweep[NO_PIECES]; + extern small_short PieceList[2][NO_SQUARES], PawnCnt[2][NO_COLS]; + extern small_short Captured[2][NO_PIECES]; + +#ifdef NOMEMSET +#define ClearCaptured() \ + { short piece, color;\ + for (color = black; color <= white; color++)\ + for (piece = 0; piece < NO_PIECES; piece++)\ + Captured[color][piece] = 0;\ + } +#else +#define ClearCaptured() \ + memset ((char *)Captured, 0,(unsigned long)sizeof(Captured)) +#endif /* NOMEMSET */ + + extern small_short Mvboard[]; + +#if !defined SAVE_SVALUE + extern short svalue[NO_SQUARES]; +#endif + extern short pscore[2]; /* eval.c */ + extern int EADD; /* eval.c */ + extern int EGET; /* eval.c */ + extern struct flags flag; + extern short opponent, computer, INCscore; + extern short WAwindow, BAwindow, WBwindow, BBwindow; + extern short dither, player; + extern short xwndw, contempt; + extern long ResponseTime, ExtraTime, TCleft, MaxResponseTime, et, et0, time0, ft; + extern int TCcount; +#ifdef INTERRUPT_TEST + extern long itime0, it; +#endif + extern long reminus, replus; + extern long GenCnt, NodeCnt, ETnodes, EvalNodes, HashAdd, HashCnt, HashCol, THashCol, + FHashCnt, FHashAdd; + extern short HashDepth, HashMoveLimit; + extern struct GameRec far *GameList; + extern short GameCnt, Game50; + extern short Sdepth, MaxSearchDepth; + extern int Book; + extern struct TimeControlRec TimeControl; + extern int TCadd; + extern short TCflag, TCmoves, TCminutes, TCseconds, OperatorTime; + extern int timecomp[MINGAMEIN], timeopp[MINGAMEIN]; + extern int compptr,oppptr; + extern short XCmore, XCmoves[], XCminutes[], XCseconds[], XC; + extern const short otherside[]; + extern const small_short Stboard[]; + extern const small_short Stcolor[]; + extern unsigned short hint; + extern short int TOflag; + extern short stage, stage2; + +#define in_opening_stage (!flag.tsume && (stage < 33)) +#define in_middlegame_stage (!flag.tsume && (stage >= 33) && (stage <= 66)) +#define in_endgame_stage (flag.tsume || (stage > 66)) + + extern short int ahead, hash; + extern short balance[2]; + extern small_short ChkFlag[], CptrFlag[], TesujiFlag[]; + extern short Pscore[], Tscore[]; + extern /*unsigned*/ short rehash; /* -1 is used as a flag --tpm */ + extern char version[], patchlevel[]; + extern unsigned int ttbllimit; + extern unsigned int TTadd; + extern unsigned int ttblsize; + extern short mtl[], hung[]; + extern small_short Pindex[]; + extern small_short PieceCnt[]; + extern short FROMsquare, TOsquare; + extern small_short HasPiece[2][NO_PIECES]; + extern const short kingP[]; + extern unsigned short killr0[], killr1[]; + extern unsigned short killr2[], killr3[]; + extern unsigned short int PrVar[MAXDEPTH]; + extern unsigned short PV, SwagHt, Swag0, Swag1, Swag2, Swag3, Swag4, sidebit; + extern short mtl[2], pmtl[2], hung[2]; + extern const small_short relative_value[]; + extern const long control[]; + extern small_short diagonal(short delta); + extern const small_short promoted[NO_PIECES],unpromoted[NO_PIECES]; + extern const small_short is_promoted[NO_PIECES]; + +typedef unsigned char next_array[NO_SQUARES][NO_SQUARES]; +typedef small_short distdata_array[NO_SQUARES][NO_SQUARES]; + + extern const small_short inunmap[NO_SQUARES]; + extern const small_short nunmap[(NO_COLS+2)*(NO_ROWS+4)]; +#if defined SAVE_NEXTPOS + extern const small_short direc[NO_PTYPE_PIECES][8]; + extern short first_direction(short ptyp, short *d, short sq); + extern short next_direction(short ptyp, short *d, short sq); + extern short next_position(short ptyp, short *d, short sq, short u); +#else + extern short use_nextpos; + extern next_array far *nextpos[NO_PTYPE_PIECES]; + extern next_array far *nextdir[NO_PTYPE_PIECES]; +#endif + + extern value_array far *value; + extern fscore_array far *fscore; + +#ifndef SAVE_DISTDATA + extern short use_distdata; + extern distdata_array far *distdata; +#endif + +#ifndef SAVE_PTYPE_DISTDATA + extern short use_ptype_distdata; + extern distdata_array far *ptype_distdata[NO_PTYPE_PIECES]; +#endif + + extern const small_short ptype[2][NO_PIECES]; + + extern long filesz,hashmask,hashbase; + extern FILE *hashfile; + extern unsigned int starttime; + + /* eval.c */ +typedef small_short Mpiece_array[2][NO_SQUARES]; + extern Mpiece_array *Mpiece[NO_PIECES]; + extern short ADVNCM[NO_PIECES]; + +#define computed_distance(a,b) \ + ((abs(column (a) - column (b)) > abs (row (a) - row (b)))\ + ? abs(column (a) - column (b)) : abs (row (a) - row (b))) + + extern short distance (short a, short b); + extern short ptype_distance (short ptyp, short f, short t); + extern short piece_distance(short side,short piece,short f,short t); + +#if defined UNKNOWN +#undef UNKNOWN +#endif + +#define UNKNOWN 'U' +#define STATIC_ROOK 'S' +#define RANGING_ROOK 'R' + + extern char GameType[2]; + void ShowGameType(void); + + extern short unsigned bookmaxply; + extern int unsigned bookcount; + extern int unsigned booksize; + extern unsigned long hashkey, hashbd; + +typedef struct hashval hashcode_array[2][NO_PIECES][NO_SQUARES]; +typedef struct hashval drop_hashcode_array[2][NO_PIECES][NO_SQUARES]; + + extern hashcode_array far *hashcode; + extern drop_hashcode_array far *drop_hashcode; + extern char far *CP[]; +#ifdef QUIETBACKGROUND + extern short background; +#endif /* QUIETBACKGROUND */ + +#if ttblsz + extern short use_ttable; + extern struct hashentry far *ttable[2]; +#endif + +/* + * hashbd contains a 32 bit "signature" of the board position. hashkey + * contains a 16 bit code used to address the hash table. When a move is + * made, XOR'ing the hashcode of moved piece on the from and to squares with + * the hashbd and hashkey values keeps things current. + */ +#define UpdateHashbd(side, piece, f, t) \ +{\ + if ((f) >= 0)\ + {\ + hashbd ^= (*hashcode)[side][piece][f].bd;\ + hashkey ^= (*hashcode)[side][piece][f].key;\ + }\ + if ((t) >= 0)\ + {\ + hashbd ^= (*hashcode)[side][piece][t].bd;\ + hashkey ^= (*hashcode)[side][piece][t].key;\ + }\ +} + +#define UpdateDropHashbd(side, piece, count) \ +{\ + hashbd ^= (*drop_hashcode)[side][piece][count].bd;\ + hashkey ^= (*drop_hashcode)[side][piece][count].key;\ +} + + + + + extern short rpthash[2][256]; + extern char *DRAW; + + +#define row(a) ((a) / 9) +#define column(a) ((a) % 9) + +#define locn(a,b) (((a)*9)+b) + +/* init external functions */ + extern void InitConst (char *lang); /* init.c */ + extern int Initialize_data (void); /* init.c */ + extern void Free_data (void); /* init.c */ + extern int Lock_data (void); /* init.c */ + extern void Unlock_data (void); /* init.c */ + extern void Initialize_dist (void); /* init.c */ + extern void Initialize_eval (void); /* eval.c */ + extern void NewGame (void); + extern int parse (FILE * fd, short unsigned int *mv, short int side, char *opening); + extern void GetOpenings (void); + extern int OpeningBook (unsigned short int *hint, short int side); + +typedef enum { REMOVE_PIECE = 1, ADD_PIECE } UpdatePieceList_mode; + + extern void UpdatePieceList (short int side, short int sq, UpdatePieceList_mode iop); + +typedef enum { FOREGROUND_MODE = 1, BACKGROUND_MODE } SelectMove_mode; + + extern void SelectMove (short int side, SelectMove_mode iop); + extern int + search (short int side, + short int ply, + short int depth, + short int alpha, + short int beta, + short unsigned int *bstline, + short int *rpt); +#ifdef CACHE + void + PutInEETable (short int side,int score); + int + CheckEETable (short int side); + int + ProbeEETable (short int side, short int *score); +#endif +#if ttblsz + extern int + ProbeTTable (short int side, + short int depth, + short int ply, + short int *alpha, + short int *beta, + short int *score); + extern int + PutInTTable (short int side, + short int score, + short int depth, + short int ply, + short int alpha, + short int beta, + short unsigned int mv); + extern void ZeroTTable (void); + extern void ZeroRPT (void); + extern void Initialize_ttable (void); + extern unsigned int urand (void); +#ifdef HASHFILE + extern void gsrand (unsigned int); + extern int + ProbeFTable (short int side, + short int depth, + short int ply, + short int *alpha, + short int *beta, + short int *score); + extern void + PutInFTable (short int side, + short int score, + short int depth, + short int ply, + short int alpha, + short int beta, + short unsigned int f, + short unsigned int t); + +#endif /* HASHFILE */ +#endif /* ttblsz */ +#if !defined SAVE_NEXTPOS + extern void Initialize_moves (void); +#endif + + extern short generate_move_flags; + + extern void MoveList (short int side, short int ply, + short int in_check, short int blockable); + extern void CaptureList (short int side, short int ply, + short int in_check, short int blockable); + + /* from ataks.c */ + extern int SqAtakd (short int square, short int side, short int *blockable); + +extern void + MakeMove (short int side, + struct leaf far *node, + short int *tempb, + short int *tempc, + short int *tempsf, + short int *tempst, + short int *INCscore); + extern void + UnmakeMove (short int side, + struct leaf far *node, + short int *tempb, + short int *tempc, + short int *tempsf, + short int *tempst); + extern void InitializeStats (void); + extern int + evaluate (short int side, + short int ply, + short int alpha, + short int beta, + short int INCscore, + short int *InChk, + short int *blockable); + extern short int ScorePosition (short int side); + extern void ExaminePosition (short side); + extern short ScorePatternDistance(short side); + extern void DetermineStage (short side); + extern void UpdateWeights (short side); + extern int InitMain (void); + extern void ExitMain (void); + extern void Initialize (void); + extern void InputCommand (char *command); + extern void ExitChess (void); + extern void ClrScreen (void); + extern void SetTimeControl (void); + extern void SelectLevel (char *sx); + extern void + UpdateDisplay (short int f, + short int t, + short int flag, + short int iscastle); + +typedef enum { COMPUTE_AND_INIT_MODE = 1, COMPUTE_MODE +#ifdef INTERRUPT_TEST + , INIT_INTERRUPT_MODE, COMPUTE_INTERRUPT_MODE +#endif + } ElapsedTime_mode; + + extern void ElapsedTime (ElapsedTime_mode iop); + extern void SetResponseTime (short int side); + extern void CheckForTimeout (int score, int globalscore, int Jscore, int zwndw); + + extern void ShowSidetoMove (void); + extern void ShowResponseTime (void); + extern void ShowPatternCount (short side, short n); + extern void SearchStartStuff (short int side); + extern void ShowDepth (char ch); + extern void TerminateSearch (int); + extern void + ShowResults (short int score, + short unsigned int *bstline, + char ch); + extern void PromptForMove (void); + extern void SetupBoard (void); + extern void algbr (short int f, short int t, short int flag); + extern void OutputMove (void); + extern void ShowCurrentMove (short int pnt, short int f, short int t); + extern void ListGame (void); + extern void ShowMessage (char *s); + extern void ClrScreen (void); + extern void gotoXY (short int x, short int y); + extern void ClrEoln (void); + extern void DrawPiece (short int sq); + extern void UpdateClocks (void); + extern void DoDebug (void); + extern void DoTable (short table[NO_SQUARES]); + extern void ShowPostnValues (void); + extern void ChangeXwindow (void); + extern void SetContempt (void); + extern void ChangeHashDepth (void); + extern void ChangeBetaWindow (void); + extern void ChangeAlphaWindow (void); + extern void GiveHint (void); + extern void ShowPrompt (void); + extern void EditBoard (void); + extern void help (void); + extern void ChangeSearchDepth (void); + extern void skip (void); + extern void skipb (void); + extern void EnPassant (short int xside, short int f, short int t, short int iop); + extern void ShowNodeCnt (long int NodeCnt); + extern void ShowLine (short unsigned int *bstline); + extern int pick (short int p1, short int p2); + extern short int repetition (void); + extern void TimeCalc (void); + extern short DropPossible (short int piece, short int side, short int sq); /* genmoves.c */ + extern short IsCheckmate (short int side, short int in_check, short int blockable); /* genmoves.c */ + + +typedef enum { VERIFY_AND_MAKE_MODE, VERIFY_AND_TRY_MODE, UNMAKE_MODE } VerifyMove_mode; + + extern int VerifyMove (char *s, VerifyMove_mode iop, unsigned short *mv); + extern void AgeTT(); + extern unsigned short TTage; + diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..b285488 --- /dev/null +++ b/src/init.c @@ -0,0 +1,1146 @@ +/* + * init.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" + + + +#if defined HASGETTIMEOFDAY && !defined THINK_C +#include +#endif + +#if defined THINK_C +#include +#endif + +#if !defined SIGTERM +#include +#endif + +#include "pattern.h" + + +unsigned int ttbllimit; + +/* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */ + + +#ifdef THINK_C +#define abs(a) (((a)<0)?-(a):(a)) +#endif +#if !defined(MSDOS) || defined(__GO32__) +#define max(a,b) (((a)<(b))?(b):(a)) +#endif +#define odd(a) ((a) & 1) + + +const small_short piece_of_ptype[NO_PTYPE_PIECES] = +{ pawn, lance, knight, silver, gold, bishop, rook, pbishop, prook, king, + pawn, lance, knight, silver, gold }; + + +const small_short side_of_ptype[NO_PTYPE_PIECES] = +{ black, black, black, black, black, black, black, black, black, black, + white, white, white, white, white }; + +#ifdef SAVE_NEXTPOS +const small_short psweep[NO_PTYPE_PIECES] = +{ false, true, false, false, false, true, true, true, true, false, + false, true, false, false, false }; +#endif + +const small_short sweep[NO_PIECES] = +{ false, false, true, false, false, false, true, true, + false, false, false, false, true, true, false }; + + +#if !defined EXTLANGFILE + +char far *CP[CPSIZE] = + +{ +/* 000:eng: */ "", +#ifdef LANGFILE +#include LANGFILE +#else +#include "gnushogi.lng" +#endif +}; + +#else + +char far *CP[CPSIZE]; + +#endif + + +short +ptype_distance (short ptyp, short f, short t) + +/* + * Determine the minimum number of moves for a piece from + * square "f" to square "t". If the piece cannot reach "t", + * the count is set to CANNOT_REACH. + */ + +#define csquare(sq) ((side == black) ? sq : (NO_SQUARES-1-sq)) +#define crow(sq) row(csquare(sq)) +#define ccol(sq) column(csquare(sq)) + +{ + short side, piece; + short colf, colt, rowf, rowt, dcol, drow; + + if ( f == t ) + return (0); + + piece = piece_of_ptype[ptyp]; + side = side_of_ptype[ptyp]; + + dcol = (colt = ccol(t)) - (colf = ccol(f)); + drow = (rowt = crow(t)) - (rowf = crow(f)); + + switch ( piece ) { + + case pawn: + if ( (dcol != 0) || (drow < 1) ) + return (CANNOT_REACH); + else + return (drow); + + case lance: + if ( (dcol != 0) || (drow < 1) ) + return (CANNOT_REACH); + else + return (1); + + case knight: + if ( odd(drow) || (odd(drow / 2) != odd(dcol)) ) + return (CANNOT_REACH); + else if ( (drow == 0) || ((drow / 2) < abs(dcol)) ) + return (CANNOT_REACH); + else + return (drow / 2); + + case silver: + if ( drow > 0 ) { + if ( odd(drow) == odd(dcol) ) + return max(abs(drow),abs(dcol)); + else + if ( abs(dcol) <= drow ) + return (drow); + else + return (max(abs(drow),abs(dcol))+1); + } else { + if ( odd(drow) == odd(dcol) ) + return (max(abs(drow),abs(dcol))); + else + return (max(abs(drow)+1,abs(dcol))+1); + }; + + case gold: + case ppawn: + case pknight: + case plance: + case psilver: + if ( abs(dcol) == 0 ) + return (abs(drow)); + else if ( drow >= 0 ) + return max(drow,abs(dcol)); + else + return (abs(dcol)-drow); + + case bishop: + if ( odd(dcol) != odd(drow) ) + return (CANNOT_REACH); + else + return ((abs(dcol) == abs(drow)) ? 1 : 2); + + case pbishop: + if ( odd(dcol) != odd(drow) ) + if ( (abs(dcol) <= 1) && (abs(drow) <= 1) ) + return (1); + else if ( abs(abs(dcol) - abs(drow)) == 1 ) + return (2); + else + return (3); + else + return ((abs(dcol) == abs(drow)) ? 1 : 2); + + case rook: + if ( (dcol == 0) || (drow == 0) ) + return (1); + else + return (2); + + case prook: + if ( (dcol == 0) || (drow == 0) ) + return (1); + else if ( (abs(dcol) == 1) && (abs(drow) == 1) ) + return (1); + else + return (2); + + case king: + return max(abs(drow),abs(dcol)); + + default: + /* should never occur */ + return (CANNOT_REACH); + + } + +} + + +#ifdef SAVE_DISTDATA +short distance (short a, short b) +{ + return (short)computed_distance(a,b); +} +#else +short distance (short a, short b) +{ + return (use_distdata ? (short)(*distdata)[(int)a][(int)b] : (short)computed_distance(a,b)); +} +#endif + + +#ifdef SAVE_PTYPE_DISTDATA +short piece_distance(short side,short piece,short f,short t) +{ + return ((f > NO_SQUARES) ? (short)1 : (short)ptype_distance(ptype[side][piece],f,t)); +} +#else +short piece_distance(short side,short piece,short f,short t) +{ + return ((f > NO_SQUARES) ? (short)1 : + (use_ptype_distdata ? (short)(*ptype_distdata[ptype[side][piece]])[f][t] : + (short)ptype_distance(ptype[side][piece],f,t))); +} +#endif + + +void +Initialize_dist (void) +{ + register short a, b, d, di, ptyp; +#ifndef SAVE_DISTDATA + for (a = 0; a < NO_SQUARES; a++) + for (b = 0; b < NO_SQUARES; b++) + { + d = abs (column (a) - column (b)); + di = abs (row (a) - row (b)); + (*distdata)[a][b] = (small_short)((d > di) ? d : di); + } +#endif +#ifndef SAVE_PTYPE_DISTDATA + for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++) + { + for (a = 0; a < NO_SQUARES; a++) + for (b = 0; b < NO_SQUARES; b++) + (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp,a,b); + } +#endif +} + + +/* + * nextpos[piece][from-square] , nextdir[piece][from-square] gives vector of + * positions reachable from from-square in ppos with piece such that the + * sequence ppos = nextpos[piece][from-square]; pdir = + * nextdir[piece][from-square]; u = ppos[sq]; do { u = ppos[u]; if(color[u] + * != neutral) u = pdir[u]; } while (sq != u); will generate the sequence of + * all squares reachable from sq. + * + * If the path is blocked u = pdir[sq] will generate the continuation of the + * sequence in other directions. + */ + + +/* + * ptype is used to separate black and white pawns, like this; ptyp = + * ptype[side][piece] piece can be used directly in nextpos/nextdir when + * generating moves for pieces that are not white pawns. + */ + +const small_short ptype[2][NO_PIECES] = +{ ptype_no_piece, ptype_pawn, ptype_lance, ptype_knight, + ptype_silver, ptype_gold, ptype_bishop, ptype_rook, + ptype_gold, ptype_gold, ptype_gold, ptype_gold, + ptype_pbishop, ptype_prook, ptype_king, + ptype_no_piece, ptype_wpawn, ptype_wlance, ptype_wknight, + ptype_wsilver, ptype_wgold, ptype_bishop, ptype_rook, + ptype_wgold, ptype_wgold, ptype_wgold, ptype_wgold, + ptype_pbishop, ptype_prook, ptype_king}; + +const small_short promoted[NO_PIECES] = +{ no_piece, ppawn, plance, pknight, psilver, gold, pbishop, prook, + ppawn, plance, pknight, psilver, pbishop, prook, king }; + +const small_short unpromoted[NO_PIECES] = +{ no_piece, pawn, lance, knight, silver, gold, bishop, rook, + pawn, lance, knight, silver, bishop, rook, king }; + +const small_short is_promoted[NO_PIECES] = +{ false, false, false, false, false, false, false, false, + true, true, true, true, true, true, false }; + +/* data used to generate nextpos/nextdir */ +#if !defined SAVE_NEXTPOS +static +#endif +const small_short direc[NO_PTYPE_PIECES][8] = +{ + 11, 0, 0, 0, 0, 0, 0, 0 , /* 0 ptype_pawn */ + 11, 0, 0, 0, 0, 0, 0, 0 , /* 1 ptype_lance */ + 21, 23, 0, 0, 0, 0, 0, 0 , /* 2 ptype_knight */ + 10, 11, 12,-12,-10, 0, 0, 0 , /* 3 ptype_silver */ + 10, 11, 12, -1, 1,-11, 0, 0 , /* 4 ptype_gold */ + 10, 12,-12,-10, 0, 0, 0, 0 , /* 5 ptype_bishop */ + 11, -1, 1,-11, 0, 0, 0, 0 , /* 6 ptype_rook */ + 10, 12,-12,-10, 11, -1, 1,-11 , /* 7 ptype_pbishop */ + 11, -1, 1,-11, 10, 12,-12,-10 , /* 8 ptype_prook */ + 10, 11, 12, -1, 1,-12,-11,-10 , /* 9 ptype_king */ + -11, 0, 0, 0, 0, 0, 0, 0 , /* 10 ptype_wpawn */ + -11, 0, 0, 0, 0, 0, 0, 0 , /* 11 ptype_wlance */ + -21,-23, 0, 0, 0, 0, 0, 0 , /* 12 ptype_wknight */ + -10,-11,-12, 12, 10, 0, 0, 0 , /* 13 ptype_wsilver */ + -10,-11,-12, 1, -1, 11, 0, 0 }; /* 14 ptype_wgold */ + + +small_short diagonal(short d) +{ return(abs(d) == 10 || abs(d) == 12); +} + + +static const small_short max_steps[NO_PTYPE_PIECES] = +{1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1 }; + +const small_short nunmap[(NO_COLS+2)*(NO_ROWS+4)] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, + -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, + -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, + -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, + -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1, + -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, + -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, + -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1, + -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + + +const small_short inunmap[NO_SQUARES] = +{ + 23, 24, 25, 26, 27, 28, 29, 30, 31, + 34, 35, 36, 37, 38, 39, 40, 41, 42, + 45, 46, 47, 48, 49, 50, 51, 52, 53, + 56, 57, 58, 59, 60, 61, 62, 63, 64, + 67, 68, 69, 70, 71, 72, 73, 74, 75, + 78, 79, 80, 81, 82, 83, 84, 85, 86, + 89, 90, 91, 92, 93, 94, 95, 96, 97, + 100,101,102,103,104,105,106,107,108, + 111,112,113,114,115,116,117,118,119 }; + +int InitFlag = false; + + +#if defined SAVE_NEXTPOS + +short next_direction(short ptyp, short *d, short sq) +{ + short delta, to, sfrom = inunmap[sq]; + do { + (*d)++; + if ( *d >= 8 ) return sq; + delta = direc[ptyp][*d]; + if ( delta == 0 ) return sq; + to = nunmap[sfrom + delta]; + } while ( to < 0 ); + return to; +} + +short next_position(short ptyp, short *d, short sq, short u) +{ + if ( *d < 4 && psweep[ptyp] ) { + short to = nunmap[inunmap[u]+direc[ptyp][*d]]; + if ( to < 0 ) + return next_direction(ptyp,d,sq); + else + return to; + } else { + return next_direction(ptyp,d,sq); + } +} + +short first_direction(short ptyp, short *d, short sq) +{ + *d = -1; + return next_direction(ptyp,d,sq); +} + +#else + +void +Initialize_moves (void) + +/* + * This procedure pre-calculates all moves for every piece from every square. + * This data is stored in nextpos/nextdir and used later in the move + * generation routines. + */ + +{ + short ptyp, po, p0, d, di, s, delta, i; + unsigned char far *ppos, *pdir; + short dest[8][9]; + short sorted[9]; + short steps[8]; + short fpo=23,tpo=120; + + for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++) + { + for (po = 0; po < NO_SQUARES; po++) + for (p0 = 0; p0 < NO_SQUARES; p0++) + { + (*nextpos[ptyp])[po][p0] = (unsigned char) po; + (*nextdir[ptyp])[po][p0] = (unsigned char) po; + } + } + + for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++) + for (po = fpo; po < tpo; po++) + if (nunmap[po] >= (small_short)0) + { + ppos = (*nextpos[ptyp])[nunmap[po]]; + pdir = (*nextdir[ptyp])[nunmap[po]]; + /* dest is a function of direction and steps */ + for (d = 0; d < 8; d++) + { + dest[d][0] = nunmap[po]; + delta = direc[ptyp][d]; + if (delta != 0) + { + p0 = po; + for (s = 0; s < max_steps[ptyp]; s++) + { + p0 = p0 + delta; + + /* + * break if (off board) or (promoted rooks wishes to + * move two steps diagonal) or (promoted + * bishops wishes to move two steps non-diagonal) + */ + if ( (nunmap[p0] < (small_short)0) || + ((ptyp == ptype_prook) && (s > 0) && diagonal(delta)) || + ((ptyp == ptype_pbishop) && (s > 0) && !diagonal(delta)) ) + break; + else + dest[d][s] = nunmap[p0]; + } + } + else + s = 0; + + /* + * sort dest in number of steps order currently no sort + * is done due to compability with the move generation + * order in old gnu chess + */ + steps[d] = s; + for (di = d; s > 0 && di > 0; di--) + if (steps[sorted[di - 1]] == 0) /* should be: < s */ + sorted[di] = sorted[di - 1]; + else + break; + sorted[di] = d; + } + + /* + * update nextpos/nextdir + */ + p0 = nunmap[po]; + pdir[p0] = (unsigned char) dest[sorted[0]][0]; + for (d = 0; d < 8; d++) + for (s = 0; s < steps[sorted[d]]; s++) + { + ppos[p0] = (unsigned char) dest[sorted[d]][s]; + p0 = dest[sorted[d]][s]; + if (d < 7) + pdir[p0] = (unsigned char) dest[sorted[d + 1]][0]; + + /* + * else is already initialized + */ + } + } + +} + +#endif + + +void +NewGame (void) + +/* + * Reset the board and other variables to start a new game. + */ + +{ + short l, c, p, max_opening_sequence; +#ifdef HASGETTIMEOFDAY + struct timeval tv; +#endif + compptr = oppptr = 0; + stage = 0; stage2 = -1; /* the game is not yet started */ + flag.illegal = flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false; + flag.material = flag.coords = flag.hash = flag.easy = flag.beep = flag.rcptr = true; + flag.stars = flag.shade = flag.back = flag.musttimeout = false; + flag.gamein = false; +#if defined(MSDOS) && !defined(SEVENBIT) + flag.rv = false; +#else + flag.rv = true; +#endif /* MSDOS && !SEVENBIT */ + mycnt1 = mycnt2 = 0; + GenCnt = NodeCnt = et0 = dither = XCmore = 0; + znodes = ZNODES; + WAwindow = WAWNDW; + WBwindow = WBWNDW; + BAwindow = BAWNDW; + BBwindow = BBWNDW; + xwndw = BXWNDW; + if (!MaxSearchDepth) + MaxSearchDepth = MAXDEPTH - 1; + contempt = 0; + GameCnt = 0; + Game50 = 1; + CptrFlag[0] = TesujiFlag[0] = false; + hint = OPENING_HINT; + ZeroRPT (); + GameType[0] = GameType[1] = UNKNOWN; + Pscore[0] = Tscore[0] = (SCORE_LIMIT+3000); + opponent = player = black; + computer = white; + for (l = 0; l < TREE; l++) + Tree[l].f = Tree[l].t = 0; + gsrand ((unsigned int) 1); + if (!InitFlag) + { + for (c = black; c <= white; c++) + for (p = pawn; p <= king; p++) + for (l = 0; l < NO_SQUARES; l++) + { + (*hashcode)[c][p][l].key = (((unsigned long) urand ())); + (*hashcode)[c][p][l].key += (((unsigned long) urand ()) << 16); + (*hashcode)[c][p][l].bd = (((unsigned long) urand ())); + (*hashcode)[c][p][l].bd += (((unsigned long) urand ()) << 16); +#ifdef LONG64 + (*hashcode)[c][p][l].key += (((unsigned long) urand ()) << 32); + (*hashcode)[c][p][l].key += (((unsigned long) urand ()) << 48); + (*hashcode)[c][p][l].bd += (((unsigned long) urand ()) << 32); + (*hashcode)[c][p][l].bd += (((unsigned long) urand ()) << 48); +#endif + } + for (c = black; c <= white; c++) + for (p = pawn; p <= king; p++) + for (l = 0; l < MAX_CAPTURED; l++) + { + (*drop_hashcode)[c][p][l].key = (((unsigned long) urand ())); + (*drop_hashcode)[c][p][l].key += (((unsigned long) urand ()) << 16); + (*drop_hashcode)[c][p][l].bd = (((unsigned long) urand ())); + (*drop_hashcode)[c][p][l].bd += (((unsigned long) urand ()) << 16); +#ifdef LONG64 + (*drop_hashcode)[c][p][l].key += (((unsigned long) urand ()) << 32); + (*drop_hashcode)[c][p][l].key += (((unsigned long) urand ()) << 48); + (*drop_hashcode)[c][p][l].bd += (((unsigned long) urand ()) << 32); + (*drop_hashcode)[c][p][l].bd += (((unsigned long) urand ()) << 48); +#endif + } + } + for (l = 0; l < NO_SQUARES; l++) + { + board[l] = Stboard[l]; + color[l] = Stcolor[l]; + Mvboard[l] = 0; + } + ClearCaptured (); + ClrScreen (); + InitializeStats (); +#ifdef HASGETTIMEOFDAY + gettimeofday(&tv, NULL); + time0 = tv.tv_sec*100+tv.tv_usec/10000; +#elif defined THINK_C + time0 = time (0); +#else + time0 = time ((long *) 0); +#endif + /* resetting reference time */ + ElapsedTime (COMPUTE_AND_INIT_MODE); + flag.regularstart = true; + Book = BOOKFAIL; + if (!InitFlag) + { + char sx[256]; + strcpy(sx,CP[169]); + if (TCflag) + SetTimeControl (); + else if (MaxResponseTime == 0) + SelectLevel (sx); + UpdateDisplay (0, 0, 1, 0); + GetOpenings (); + GetOpeningPatterns (&max_opening_sequence); +#ifdef DEBUG + /* ShowOpeningPatterns (max_opening_sequence); */ +#endif + InitFlag = true; + } +#if ttblsz + if(TTadd){ZeroTTable (); TTadd = 0;} +#endif /* ttblsz */ + hashbd = hashkey = 0; + return; +} + + + +int +Initialize_data (void) +{ + size_t n; + int i; + char buffer[60],buf2[60]; + int doit = true; + + { + small_short x = -1; + if ( x >= 0 ) { + ShowMessage("datatype 'small_short' is unsigned; check gnushogi.h\n"); + return(1); + } + } + + n = sizeof(struct leaf) * (size_t)TREE; + Tree = HEAP_ALLOC(n); + if ( ! Tree ) { + sprintf(buffer,"Cannot allocate %ld bytes for search tree",n); + ShowMessage (buffer); + return(1); + } else { +#if defined DEBUG + printf("Tree memory: %ld\n",(long)n); +#endif + } + + n = sizeof(hashcode_array); + hashcode = HEAP_ALLOC(n); + if ( !hashcode ) { + sprintf(buffer,"Cannot allocate %ld bytes for hashcode",n); + ShowMessage(buffer); + return(1); + } else { +#if defined DEBUG + printf("hashcode memory: %ld\n",(long)n); +#endif + } + + n = sizeof(drop_hashcode_array); + drop_hashcode = HEAP_ALLOC(n); + if ( !drop_hashcode ) { + sprintf(buffer,"Cannot allocate %ld bytes for drop_hashcode",n); + ShowMessage(buffer); + return(1); + } else { +#if defined DEBUG + printf("drop_hashcode memory: %ld\n",(long)n); +#endif + } + + n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH); + GameList = HEAP_ALLOC(n); + if ( !GameList ) { + sprintf(buffer,"Cannot allocate %ld bytes for game record",n); + ShowMessage(buffer); + return(1); + } else { +#ifdef DEBUG + printf("GameList memory: %ld\n",(long)n); +#endif + } + +#if !defined SAVE_NEXTPOS + n = sizeof(next_array); + for ( i=0; i MINTTABLE ) { +#ifdef DEBUG + printf("try to allocate %d bytes for transposition table\n",(long)2*n); +#endif + ttable[0] = HEAP_ALLOC(n); + ttable[1] = ttable[0] ? HEAP_ALLOC(n) : NULL; + if ( !ttable[0] || !ttable[1] ) { + if ( !ttable[0] ) { + HEAP_FREE(ttable[0]); + } + if ( !ttable[1] ) { + HEAP_FREE(ttable[1]); + } + ttblsize = ttblsize >> 1; + n = sizeof(struct hashentry)*(ttblsize+rehash); + } else doit = false; + } + if ( ttblsize <= MINTTABLE ) { + use_ttable = false; + } + if ( use_ttable ) { +#if defined DEBUG + sprintf(buffer,"ttable's memory: %ld, ttblsize=%ld rehash=%ld", + (long)2*n,(long)ttblsize,(long)rehash); + ShowMessage(buffer); +#endif + ttbllimit = ttblsize<<1 - ttblsize>>2; +#ifdef DEBUG_TTABLE + printf("ttbllimit = %ld\n",(long)ttbllimit); +#endif + } else { + sprintf(buffer,"Cannot allocate %ld bytes for transposition table",(long)(2*n)); + ShowMessage (buffer); + ttable[0] = ttable[1] = NULL; + } +#endif /* ttblsz */ + +#if !defined SAVE_DISTDATA + n = sizeof(distdata_array); + distdata = HEAP_ALLOC(n); + if ( !distdata ) + { + ShowMessage("cannot allocate distdata space..."); + use_distdata = false; + } + else + { +#if defined DEBUG + printf("distdata memory: %ld\n",(long)n); +#endif + } +#endif + +#if !defined SAVE_PTYPE_DISTDATA + n = sizeof(distdata_array); + for ( i=0; i &s[8]; q--) + if (*q == '}') + break; + if (q == &s[8]) + { + ShowMessage("{ error in cinstfile"); + exit (1); + } + *q = '\0'; + if (s[3] != ':' || s[7] != ':' || s[8] != '{') + { + sprintf (buffer,"Langfile format error %s", s); + ShowMessage(buffer); + exit (1); + } + s[3] = s[7] = '\0'; + if (lang == NULL) + { + lang = sl; + strcpy (sl, &s[4]); + } + if (strcmp (&s[4], lang)) + continue; + entry = atoi (s); + if (entry < 0 || entry >= CPSIZE) + { + ShowMessage("Langfile number error"); + exit (1); + } + for (q = p = &s[9]; *p; p++) + { + if (*p != '\\') + { + *q++ = *p; + } + else if (*(p + 1) == 'n') + { + *q++ = '\n'; + p++; + } + } + *q = '\0'; + if (entry < 0 || entry > 255) + { + sprintf (buffer,"Langfile error %d\n", entry); + ShowMessage(buffer); + exit (0); + } + CP[entry] = (char far *) GLOBAL_ALLOC ((unsigned) strlen (&s[9]) + 1); + if (CP[entry] == NULL) + { + char buffer[80]; + sprintf(buffer,"CP MALLOC, entry %d",entry); + perror (buffer); + exit (0); + } + strcpy (CP[entry], &s[9]); + + } + fclose (constfile); +} + +#else + +void +InitConst (char *lang) +{ + FILE *constfile; + char s[256]; + char sl[5]; + char buffer[120]; + int len, entry; + char *p, *q; + constfile = fopen (LANGFILE, "r"); + if (!constfile) + { + ShowMessage ("NO LANGFILE"); + exit (1); + } + while (fgets (s, sizeof (s), constfile)) + { + if (s[0] == '!') + continue; + len = strlen (s); + if (len > 3 && s[3] == ':' || len > 7 && s[7] == ':' ) + { + ShowMessage("old Langfile error"); + exit (1); + } + if (len <= 15) + { + ShowMessage("length error in Langfile"); + exit (1); + } + for (q = &s[len]; q > &s[15]; q--) + if (*q == '"') + break; + if (q == &s[15]) + { + ShowMessage("\" error in Langfile"); + exit (1); + } + *q = '\0'; + if (s[6] != ':' || s[10] != ':' || s[15] != '"') + { + sprintf (buffer,"Langfile format error %s", s); + ShowMessage(buffer); + exit (1); + } + s[6] = s[10] = '\0'; + if (lang == NULL) + { + lang = sl; + strcpy (sl, &s[7]); + } + if (strcmp (&s[7], lang)) + continue; + entry = atoi (&s[3]); + if (entry < 0 || entry >= CPSIZE) + { + ShowMessage("Langfile number error"); + exit (1); + } + for (q = p = &s[16]; *p; p++) + { + if (*p != '\\') + { + *q++ = *p; + } + else if (*(p + 1) == 'n') + { + *q++ = '\n'; + p++; + } + } + *q = '\0'; + if (entry < 0 || entry > 255) + { + sprintf (buffer,"Langfile error %d\n", entry); + ShowMessage(buffer); + exit (0); + } + CP[entry] = (char far *) GLOBAL_ALLOC ((unsigned) strlen (&s[16]) + 1); + if (CP[entry] == NULL) + { + char buffer[80]; + sprintf(buffer,"CP MALLOC, entry %d",entry); + perror (buffer); + exit (0); + } + strcpy (CP[entry], &s[16]); + + } + fclose (constfile); +} + +#endif + +#endif + + +int +InitMain (void) +{ +#if defined THINK_C + gsrand (starttime = ((unsigned int) time ((time_t *) 0))); /* init urand */ +#else + gsrand (starttime = ((unsigned int) time ((long *) 0))); /* init urand */ +#endif + +#if ttblsz + ttblsize = ttblsz; + rehash = -1; +#endif /* ttblsz */ + + if ( Initialize_data() != 0 ) + return(1); + +#if defined EXTLANGFILE + InitConst (Lang); +#endif + + strcpy(ColorStr[0],CP[118]); + strcpy(ColorStr[1],CP[119]); + + XC = 0; + MaxResponseTime = 0; + +#if defined XSHOGI + signal (SIGTERM, TerminateSearch); +#endif + +#if defined XSHOGI + TCflag = true; + TCmoves = 40; + TCminutes = 5; + TCseconds = 0; + TCadd = 0; + OperatorTime = 0; +#else + TCflag = false; + OperatorTime = 0; +#endif + + Initialize (); + Initialize_dist (); + Initialize_eval (); +#if !defined SAVE_NEXTPOS + Initialize_moves (); +#endif + + NewGame (); + + flag.easy = ahead; + flag.hash = hash; + if (xwin) + xwndw = atoi (xwin); + +#ifdef HASHFILE + hashfile = NULL; +#endif + +#if ttblsz +#ifdef HASHFILE + hashfile = fopen (HASHFILE, RWA_ACC); + if (hashfile) + { + fseek (hashfile, 0L, SEEK_END); + filesz = ftell (hashfile) / sizeof (struct fileentry) - 1 - MAXrehash; + hashmask = filesz>>1; + hashbase = hashmask+1; + } +#endif /* HASHFILE */ +#endif /* ttblsz */ + + savefile[0] = '\0'; + listfile[0] = '\0'; + + return(0); + +} + + +void +ExitMain (void) +{ +#if ttblsz +#ifdef HASHFILE + if (hashfile) + fclose (hashfile); +#endif /* HASHFILE */ +#endif /* ttblsz */ + + ExitChess (); +} + + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f9cb6dc --- /dev/null +++ b/src/main.c @@ -0,0 +1,372 @@ +/* + * main.c - C source for GNU SHOGI based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback (GNU Chess) + * Copyright (c) 1992 Free Software Foundation + * Copyright (c) 1993,1994,1995 Matthias Mutz (GNU Shogi) + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "version.h" +#include "gnushogi.h" + +#include + + +#if defined THINK_C +#include +#include +#endif + + + + +#ifdef DEBUG_INITS + +/* print all possible moves for all pieces from all squares */ + +void DebugInits () +{ + register short u, sq; + register unsigned char *ppos, *pdir; + char s[10]; + short piece, ptyp; + + for ( piece = 0; piece < NO_PIECES; piece++ ) { + printf("move list for piece %i\n",piece); + for ( sq = 0; sq < NO_SQUARES; sq++ ) { + printf(" from square %i to ",sq); + ptyp = ptype[black][piece]; + ppos = (*nextpos)[ptyp][sq]; + u = ppos[sq]; + do { + printf("%i",u); + u = ppos[u]; + if (u != sq) printf(", "); + } while (u != sq); + printf("\n"); + }; + /* pdir = (*nextdir)[ptyp][sq]; */ + printf("\n"); + scanf("%s",s); + if ( strcmp(s,"exit") == 0 ) + exit(0); + }; +} + +#endif + + + +int +main (int argc, char **argv) +{ + +#ifdef THINK_C + console_options.ncols = 100; + cshow(stdout); +#ifdef NONDSP + ccommand(&argv); +#endif +#endif + + if (argc > 2) + { + if (argv[1][0] == '-' && argv[1][1] == 'L') + { + Lang = argv[2]; + argv += 2; + argc -= 2; + } + } + + while (argc > 1 && ((argv[1][0] == '-') || (argv[1][0] == '+'))) + { + switch (argv[1][1]) + { + case 'a': + ahead = ((argv[1][0] == '-') ? false : true); + break; + case 'b': + argv++; + argc--; + if (argc > 1) + { + bookfile = argv[1]; +#ifdef BINBOOK + binbookfile = NULL; +#endif + } + break; +#ifdef BINBOOK + case 'B': + argv++; + argc--; + if (argc > 1) + binbookfile = argv[1]; + break; +#endif + case 'h': + hash = ((argv[1][0] == '-') ? false : true); + break; + case 's': + argc--; + argv++; + if (argc > 1) + strcpy (savefile, argv[1]); + break; + case 'l': + argc--; + argv++; + if (argc > 1) + strcpy (listfile, argv[1]); + break; + case 'S': + argc--; + argv++; + if(argc > 1)booksize = atoi(argv[1]); + break; + case 'P': + argc--; + argv++; + if(argc > 1)bookmaxply = atoi(argv[1]); + break; + +#if ttblsz + case 'r': + if (argc > 2) + rehash = atoi (argv[2]); + argc--; + argv++; + if (rehash > MAXrehash) + rehash = MAXrehash; + break; + case 'T': + if (argc > 2) + ttblsize = atoi (argv[2]); + argc--; + argv++; + if ((ttblsize <= MINTTABLE)) ttblsize = (MINTTABLE)+1; + break; +#ifdef HASHFILE + case 't': /* create or test persistent transposition + * table */ + hashfile = fopen (HASHFILE, RWA_ACC); + if (hashfile) + { + fseek (hashfile, 0L, SEEK_END); + filesz = (ftell (hashfile) / sizeof (struct fileentry)) - 1; + } + if (hashfile != NULL) + { + long i, j; + int nr[MAXDEPTH]; + struct fileentry n; + + printf (CP[49]); + for (i = 0; i < MAXDEPTH; i++) + nr[i] = 0; + fseek (hashfile, 0L, SEEK_END); + i = ftell (hashfile) / sizeof (struct fileentry); + fseek (hashfile, 0L, SEEK_SET); + for (j = 0; j < i + 1; j++) + { + fread (&n, sizeof (struct fileentry), 1, hashfile); +if(n.depth >MAXDEPTH) {printf("ERROR\n");exit(1);} + if (n.depth) + { + nr[n.depth]++; + nr[0]++; + } + } + printf (CP[109], + nr[0], i); + for (j = 1; j < MAXDEPTH; j++) + printf ("%d ", nr[j]); + printf ("\n"); + } + return 0; + case 'c': /* create or test persistent transposition + * table */ + if (argc > 2) + filesz = atoi (argv[2]); + else + filesz = vfilesz; + if (filesz > 0 && filesz < 24) + filesz = (1 << filesz) - 1 + MAXrehash; + else + filesz = filesz + MAXrehash; +#ifdef HASHFILE + if ((hashfile = fopen (HASHFILE, RWA_ACC)) == NULL) + hashfile = fopen (HASHFILE, WA_ACC); + if (hashfile != NULL) + { + long j; + struct fileentry n; + + printf (CP[66]); + n.f = n.t = 0; + n.flags = 0; + n.depth = 0; + n.sh = n.sl = 0; + for (j = 0; j < filesz + 1; j++) + fwrite (&n, sizeof (struct fileentry), 1, hashfile); + fclose (hashfile); + } + else + printf (CP[50], HASHFILE); +#endif + return (0); +#endif /* HASHFILE */ +#endif /* ttblsz */ + case 'x': + xwin = &argv[1][2]; + break; + case 'v': + fprintf (stderr, CP[102], version, patchlevel); + exit (1); + default: + fprintf (stderr, CP[113]); + exit (1); + } + argv++; + argc--; + } + + if (argc == 2) + { + char *p; + + MaxResponseTime = 100L * strtol (argv[1], &p, 10); + if (*p == ':') + MaxResponseTime = 60L * MaxResponseTime + + 100L * strtol (++p, (char **) NULL, 10); + TCflag = false; + TCmoves = 0; + TCminutes = 0; + TCseconds = 0; + } + + if (argc >= 3) + { + char *p; + if (argc > 9) + { + printf ("%s\n", CP[220]); + exit (1); + } + TCmoves = atoi (argv[1]); + TCminutes = (short)strtol (argv[2], &p, 10); + if (*p == ':') + TCseconds = (short)strtol (p + 1, (char **) NULL, 10); + else + TCseconds = 0; + TCflag = true; + argc -= 3; + argv += 3; + while (argc > 1) + { + XCmoves[XC] = atoi (argv[0]); + XCminutes[XC] = (short)strtol (argv[1], &p, 10); + if (*p == ':') + XCseconds[XC] = (short)strtol (p + 1, (char **) NULL, 10); + else + XCseconds[XC] = 0; + if (XCmoves[XC] && (XCminutes[XC] || XCseconds[XC])) + XC++; + else + { + printf (CP[220]); + exit (1); + } + argc -= 2; + argv += 2; + } + if (argc) + { + printf ("%s\n", CP[220]); + exit (1); + } + } + + if ( InitMain() != 0 ) + exit(1); + +#ifdef DEBUG_INITS + DebugInits (); +#endif + + while (!(flag.quit)) + { + oppptr = (oppptr + 1) % MINGAMEIN; + if (flag.bothsides && !flag.mate) { + SelectMove (opponent, FOREGROUND_MODE); + } else + InputCommand (NULL); + if (opponent == white) + if (flag.gamein || TCadd) + { + TimeCalc (); + } + else if (TimeControl.moves[opponent] == 0) + { + if (XC) + if (XCmore < XC) + { + TCmoves = XCmoves[XCmore]; + TCminutes = XCminutes[XCmore]; + TCseconds = XCseconds[XCmore]; + XCmore++; + } + SetTimeControl (); + } + + compptr = (compptr + 1) % MINGAMEIN; + if (!(flag.quit || flag.mate || flag.force)) + { +#ifdef INTTERRUPT_TEST + printf("starting search...\n"); +#endif + SelectMove (computer, FOREGROUND_MODE); + if (computer == white) + if (flag.gamein) + { + TimeCalc (); + } + else if (TimeControl.moves[computer] == 0) + { + if (XC) + if (XCmore < XC) + { + TCmoves = XCmoves[XCmore]; + TCminutes = XCminutes[XCmore]; + TCseconds = XCseconds[XCmore]; + XCmore++; + } + SetTimeControl (); + } + } + } + + ExitMain (); + + return (0); +} + + diff --git a/src/nondsp.c b/src/nondsp.c new file mode 100644 index 0000000..9686a29 --- /dev/null +++ b/src/nondsp.c @@ -0,0 +1,831 @@ +/* + * nondsp.c - UNIX & MSDOS AND NON-DISPLAY interface for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ +extern int EADD,EGET; +#include +#include +#if defined THINK_C +#include +#elif defined MSDOS +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +void TerminateSearch (int), Die (int); + +#endif /* MSDOS */ + +#include "gnushogi.h" + +#ifdef DEBUG +short int debuglevel = 1024; +#endif /* DEBUG */ +unsigned short int MV[MAXDEPTH]; +int MSCORE; + +#if defined XSHOGI +short int xshogi = 1; + +#else +short int xshogi = 0; + +#endif /* XSHOGI */ +int mycnt1, mycnt2; +char *DRAW; +extern char *InPtr; +extern short int pscore[]; + +void +Initialize (void) +{ + mycnt1 = mycnt2 = 0; +#if defined XSHOGI && !defined THINK_C && !defined MSDOS +#ifndef SYSV + setlinebuf (stdout); +#else + setvbuf (stdout, NULL, _IOLBF, BUFSIZ); +#endif + printf ("GNU Shogi %sp%s\n", version, patchlevel); +#endif XSHOGI +#ifdef HARDTIMELIMIT + if (!TCflag && (MaxResponseTime == 0)) + MaxResponseTime = 15L*100L; +#endif +} + +void +ExitChess (void) +{ + signal (SIGTERM, SIG_IGN); +#ifndef NOLIST + ListGame (); +#endif +} + +#ifndef MSDOS /* never called!!! */ +void +Die (int sig) +{ + char s[80]; + + ShowMessage (CP[31]); /*Abort?*/ + scanz ("%s", s); + if (strcmp (s, CP[210]) == 0) /*yes*/ + ExitChess (); +} + +#endif /* MSDOS */ + +void +TerminateSearch (int sig) +{ +#ifdef MSDOS + sig++; /* shut up the compiler */ +#endif /* MSDOS */ +#ifdef INTERRUPT_TEST + ElapsedTime(INIT_INTERRUPT_MODE); +#endif + if (!flag.timeout) + flag.back = true; /* previous: flag.timeout = true; */ + flag.bothsides = false; +#ifdef DEBUG + printf("Terminate Search\n"); +#endif +} + + + + +void +help (void) +{ + ClrScreen (); + /*printz ("SHOGI command summary\n");*/ + printz (CP[40]); + printz ("----------------------------------------------------------------\n"); + /*printz ("7g7f move from 7g to 7f quit Exit Shogi\n");*/ + printz (CP[158]); + /*printz ("S6h move silver to 6h beep turn %s\n", (flag.beep) ? "off" : "on");*/ + printz (CP[86], (flag.beep) ? CP[92] : CP[93]); + /*printz ("2d2c+ move from 2d to 2c and promote\n");*/ + printz (CP[128], (flag.material) ? CP[92] : CP[93]); + /*printz ("P*5e drop pawn to 5e easy turn %s\n", (flag.easy) ? "off" : "on");*/ + printz (CP[173], (flag.easy) ? CP[92] : CP[93]); + /*printz (" hash turn %s\n", (flag.hash) ? "off" : "on");*/ + printz (CP[174], (flag.hash) ? CP[92] : CP[93]); + /*printz ("bd redraw board reverse board display\n");*/ + printz (CP[130]); + /*printz ("list game to shogi.lst book turn %s used %d of %d\n", (Book) ? "off" : "on", bookcount);*/ + printz (CP[170], (Book) ? CP[92] : CP[93], bookcount,booksize); + /*printz ("undo undo last ply remove take back a move\n");*/ + printz (CP[200]); + /*printz ("edit edit board force enter game moves\n");*/ + printz (CP[153]); + /*printz ("switch sides with computer both computer match\n");*/ + printz (CP[194]); + /*printz ("black computer plays black white computer plays white\n");*/ + printz (CP[202]); + /*printz ("depth set search depth clock set time control\n");*/ + printz (CP[149]); + /*printz ("post principle variation hint suggest a move\n");*/ + printz (CP[177]); + /*printz ("save game to file get game from file\n");*/ + printz (CP[188]); + printz ("xsave pos. to xshogi file xget pos. from xshogi file\n"); + /*printz ("random randomize play new start new game\n");*/ + printz (CP[181]); + printz ("----------------------------------------------------------------\n"); + /*printz ("Computer: %-12s Opponent: %s\n",*/ + printz (CP[46], + ColorStr[computer], ColorStr[opponent]); + /*printz ("Depth: %-12d Response time: %d sec\n",*/ + printz (CP[51], + MaxSearchDepth, MaxResponseTime/100); + /*printz ("Random: %-12s Easy mode: %s\n",*/ + printz (CP[99], + (dither) ? CP[93] : CP[92], (flag.easy) ? CP[93] : CP[92]); + /*printz ("Beep: %-12s Transposition file: %s\n",*/ + printz (CP[36], + (flag.beep) ? CP[93] : CP[92], (flag.hash) ? CP[93] : CP[92]); + /*printz ("Tsume: %-12s Force: %s\n")*/ + printz (CP[232], + (flag.tsume) ? CP[93] : CP[92], (flag.force) ? CP[93] : CP[92]); + /*printz ("Time Control %s %d moves %d seconds %d opr %d depth\n", (TCflag) ? "ON" : "OFF",*/ + printz (CP[110], (TCflag) ? CP[93] : CP[92], + TimeControl.moves[black], TimeControl.clock[black] / 100, TCadd/100, MaxSearchDepth); + signal (SIGINT, TerminateSearch); +#if !defined MSDOS && !defined THINK_C + signal (SIGQUIT, TerminateSearch); +#endif /* MSDOS */ +} + + +void +EditBoard (void) + +/* + * Set up a board position. Pieces are entered by typing the piece followed + * by the location. For example, Nf3 will place a knight on square f3. + */ + +{ + short a, r, c, sq, i, found; + char s[80]; + + flag.regularstart = true; + Book = BOOKFAIL; + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); + /*printz (". exit to main\n");*/ + printz (CP[29]); + /*printz ("# clear board\n");*/ + printz (CP[28]); + /*printz ("c change sides\n");*/ + printz (CP[136]); + /*printz ("enter piece & location: \n");*/ + printz (CP[155]); + + a = black; + do + { + scanz ("%s", s); + found=0; + if (s[0] == CP[28][0]) /*#*/ + { short side; + for (sq = 0; sq < NO_SQUARES; sq++) + { + board[sq] = no_piece; + color[sq] = neutral; + }; + ClearCaptured (); + } + if (s[0] == CP[136][0]) /*c*/ + a = otherside[a]; + if ( s[1] == '*' ) + { + for ( i = pawn; i <= king; i++) + if ((s[0] == pxx[i]) || (s[0] == qxx[i])) + { + Captured[a][i]++; + found=1; + break; + } + c = -1; + r = -1; + } + else + { + c = '9' - s[1]; + r = 'i' - s[2]; + } + if ((c >= 0) && (c < NO_COLS) && (r >= 0) && (r < NO_ROWS)) + { + sq = locn (r, c); + color[sq] = a; + board[sq] = no_piece; + for (i = no_piece; i <= king; i++) + if ((s[0] == pxx[i]) || (s[0] == qxx[i])) + { + if ( s[3] == '+' ) + board[sq] = promoted[i]; + else + board[sq] = i; + found=1; + break; + } + if (found==0) color[sq] = neutral; + } + } while (s[0] != CP[29][0]); + for (sq = 0; sq < NO_SQUARES; sq++) + Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0); + GameCnt = 0; + Game50 = 1; + ZeroRPT (); + Sdepth = 0; + InitializeStats (); + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); +} + +void +SetupBoard (void) + +/* + * Set up a board position. + * Nine lines of nine characters are used to setup the board. 9a-1a is the + * first line. White pieces are represented by uppercase characters. + */ + +{ + short r, c, sq, i; + char ch; + char s[80]; + + NewGame (); + + gets (s); /* skip "setup" command */ + for (r = NO_ROWS-1; r >= 0; r--) + { + gets (s); + for (c = 0; c <= (NO_COLS-1); c++) + { + ch = s[c]; + sq = locn (r, c); + color[sq] = neutral; + board[sq] = no_piece; + for (i = no_piece; i <= king; i++) + if (ch == pxx[i]) + { + color[sq] = white; + board[sq] = i; + break; + } + else if (ch == qxx[i]) + { + color[sq] = black; + board[sq] = i; + break; + } + } + } + for (sq = 0; sq < NO_SQUARES; sq++) + Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0); + InitializeStats (); + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); + /*printz ("Setup successful\n");*/ + printz (CP[106]); +} + +void +ShowDepth (char ch) +{ +#ifdef MSDOS + ch++; /* shut up the compiler */ +#endif /* MSDOS */ +#if !defined BAREBONES + printz (CP[53], Sdepth, ch); /*Depth= %d%c*/ + printz ("\n"); +#endif +} + + +void +ShowStage (void) +{ + printz("stage = %d\n",stage); + printz("balance[black] = %d balance[white] = %d\n",balance[black],balance[white]); +} + + +void +ShowLine (short unsigned int *bstline) +{ + register int i; + + for (i = 1; bstline[i] > 0; i++) + { + if ((i > 1) && (i % 8 == 1)) + printf ("\n "); + algbr ((short) (bstline[i] >> 8), (short) (bstline[i] & 0xFF), false); + printf ("%5s ", mvstr[0]); + } + printf ("\n"); +} + +void +ShowResults (short int score, short unsigned int *bstline, char ch) +{ + if (flag.post) + { + ElapsedTime (2); + printf ("%2d%c %6d %4ld %8ld ", Sdepth, ch, score, et / 100, NodeCnt); + ShowLine (bstline); + } +} + +void +ShowPatternCount (short side, short n) +{ + if (flag.post) + { + printz("%s matches %d pattern(s)\n",ColorStr[side],n); + } +} + +void +ShowResponseTime (void) +{ +#ifdef DEBUG + if (flag.post) + { + printz("RT=%ld TCC=%d TCL=%ld EX=%ld ET=%ld TO=%d\n", + ResponseTime,TCcount,TCleft,ExtraTime,et,flag.timeout); + } +#endif +} + +void +ShowGameType (void) +{ + if (flag.post) + { + printz("%c vs. %c\n",GameType[black],GameType[white]); + } +} + +void +SearchStartStuff (short int side) +{ + signal (SIGINT, TerminateSearch); +#if !defined MSDOS && !defined THINK_C + signal (SIGQUIT, TerminateSearch); +#endif /* MSDOS */ + if (flag.post) + { + printf (CP[123], + GameCnt/2+1, + ResponseTime, TimeControl.clock[side]); + } +} +void +OutputMove (void) +{ +#ifdef DEBUG11 + if (1) + { + FILE *D; + extern unsigned short int PrVar[]; + char d[80]; + int r, c, l, i; + D = fopen ("/tmp/DEBUGA", "a+"); + fprintf (D, "inout move is %s\n", mvstr[0]); + strcpy (d, mvstr[0]); + for (i = 1; PrVar[i] > 0; i++) + { + algbr ((short) (PrVar[i] >> 8), (short) (PrVar[i] & 0xFF), false); + fprintf (D, "%5s ", mvstr[0]); + } + fprintf (D, "\n"); + fprintf_current_board (D); + fclose (D); + strcpy (mvstr[0], d); + } +#endif + if (flag.illegal) {printf("%s\n",CP[225]);return;} + if (mvstr[0][0] == '\0') goto nomove; +#ifdef XSHOGI + /* add remaining time in milliseconds to xshogi */ + printz ("%d. ... %s %ld\n", ++mycnt1, mvstr[0], (TimeControl.clock[player]-et)*10); +#else + printz ("%d. ... %s\n", ++mycnt1, mvstr[0]); +#endif +#ifdef notdef /* optional pass best line to frontend with move */ + if (flag.post) + { + register int i; + + printz (" %6d%c ", MSCORE, MV[30]); + for (i = 1; MV[i] > 0; i++) + { + algbr ((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false); + printz ("%5s ", mvstr[0]); + } + } + printz ("\n"); +#endif +nomove: + if ((root->flags & draw)||(root->score == -(SCORE_LIMIT+999))|| + (root->score == (SCORE_LIMIT+998))) goto summary; + if (flag.post) + { + short h, l, t; + + h = TREE; + l = 0; + t = TREE >> 1; + while (l != t) + { + if (Tree[t].f || Tree[t].t) + l = t; + else + h = t; + t = (l + h) >> 1; + } + /*printf ("Nodes %ld Tree %d Eval %ld Rate %ld RS high %ld low %ld\n",*/ + printf (CP[89],GenCnt,NodeCnt,t,EvalNodes,(et>100)?(NodeCnt/(et/100)):0,EADD,EGET,reminus,replus); + /*printf ("Hin/Hout/Coll/Fin/Fout = %ld/%ld/%ld/%ld/%ld\n",*/ + printf (CP[71], + HashAdd, HashCnt, THashCol, HashCol,FHashCnt, FHashAdd); + } + UpdateDisplay (root->f, root->t, 0, root->flags); + if ( !xshogi ) + { + /*printf ("My move is: %s\n", mvstr[0]);*/ + printf (CP[83], mvstr[0]); + if (flag.beep) + printz ("%c", 7); + } + summary: + if (root->flags & draw) + /* printf ("Drawn game!\n");*/ + printf (CP[57]); + else if (root->score == -(SCORE_LIMIT+999)) + printf("%s mates!\n",ColorStr[opponent]); + else if (root->score == (SCORE_LIMIT+998)) + printf("%s mates!\n",ColorStr[computer]); +#if !defined BAREBONES +#ifdef VERYBUGGY + else if (root->score < -SCORE_LIMIT) + printf("%s has a forced mate in %d moves!\n", + ColorStr[opponent], SCORE_LIMIT+999 + root->score - 1); + else if (root->score > SCORE_LIMIT) + printf("%s has a forced mate in %d moves!\n", + ColorStr[computer], SCORE_LIMIT+998 - root->score - 1); +#endif /*VERYBUGGY*/ +#endif /* BAREBONES */ +} + +void +ClrScreen (void) +{ +#if !defined BAREBONES + printz ("\n"); +#endif +} + +void +UpdateDisplay (short int f, short int t, short int redraw, short int isspec) +{ + + short r, c, l, m; + + if (redraw && !xshogi) + { + printz ("\n"); + r = (short)(TimeControl.clock[black] / 6000); + c = (short)((TimeControl.clock[black] % 6000) / 100); + l = (short)(TimeControl.clock[white] / 6000); + m = (short)((TimeControl.clock[white] % 6000) / 100); + /*printz ("Black %d:%02d White %d:%02d\n", r, c, l, m);*/ + printz (CP[116], r, c, l, m); + printz ("\n"); + for (r = (NO_ROWS-1); r >= 0; r--) + { + for (c = 0; c <= (NO_COLS-1); c++) + { char pc; + l = ((flag.reverse) ? locn ((NO_ROWS-1) - r, (NO_COLS-1) - c) : locn (r, c)); + pc = (is_promoted[board[l]] ? '+' : ' '); + if (color[l] == neutral) + printz (" -"); + else if (color[l] == black) + printz ("%c%c", pc, qxx[board[l]]); + else + printz ("%c%c", pc, pxx[board[l]]); + } + printz ("\n"); + } + printz ("\n"); + { + short side; + for (side = black; side <= white; side++) + { short piece, c; + printz((side==black)?"black ":"white "); + for (piece = pawn; piece <= king; piece++) + if (c = Captured[side][piece]) + printz("%i%c ",c,pxx[piece]); + printz("\n"); + }; + } + } +} + +void +ShowMessage (char *s) +{ + printf("%s\n", s); +} + +void +ShowSidetoMove (void) +{ +} + +void +PromptForMove (void) +{ +#if !defined BAREBONES + /*printz ("\nYour move is? ");*/ + printz (CP[124]); +#endif /* BAREBONES */ +} + + +void +ShowCurrentMove (short int pnt, short int f, short int t) +{ +#ifdef MSDOS + f++; + t++; + pnt++; /* shut up the compiler */ +#endif /* MSDOS */ +} + +void +ChangeAlphaWindow (void) +{ + printz ("WAwindow: "); + scanz ("%hd", &WAwindow); + printz ("BAwindow: "); + scanz ("%hd", &BAwindow); +} + +void +ChangeBetaWindow (void) +{ + printz ("WBwindow: "); + scanz ("%hd", &WBwindow); + printz ("BBwindow: "); + scanz ("%hd", &BBwindow); +} + +void +GiveHint (void) +{ + if (hint) + { + algbr ((short) (hint >> 8), (short) (hint & 0xFF), false); + printf(CP[72], mvstr[0]); /*hint*/ + } + else + printz (CP[223]); +} + +void +SelectLevel (char *sx) +{ + + char T[NO_SQUARES], *p, *q; + + if ( (p = strstr(sx,CP[169])) != NULL ) + p += strlen(CP[169]); + else if ( (p = strstr(sx,CP[217])) != NULL ) + p += strlen(CP[217]); + strcat(sx,"XX"); + q = T; *q = '\0'; + for(;*p != 'X';*q++ = *p++); + *q = '\0'; +/* line empty ask for input */ + if(!T[0]){ printz (CP[61]); gets(T); strcat(T,"XX"); } +/* skip blackspace */ + for (p = T; *p == ' '; p++) ; +/* could be moves or a fischer clock */ + if(*p == 'f') { /* its a fischer clock game */ + p++; + TCminutes = (short)strtol(p,&q,10); + TCadd = (short)strtol(q,NULL,10) *100; + TCseconds = 0; + TCmoves = 50; + } else { /* regular game */ + TCadd = 0; + TCmoves = (short)strtol (p, &q, 10); + TCminutes = (short)strtol (q, &q, 10); + if (*q == ':') + TCseconds = (short)strtol (q + 1, (char **) NULL, 10); + else + TCseconds = 0; +#ifdef OPERATORTIME + printz (CP[94]); + scanz ("%hd", &OperatorTime); +#endif + if (TCmoves == 0) { + TCflag = false; + MaxResponseTime = TCminutes*60L*100L + TCseconds*100L; + TCminutes = TCseconds = 0; + } else { + TCflag = true; + MaxResponseTime = 0; + } +} + TimeControl.clock[black] = TimeControl.clock[white] = 0; + SetTimeControl (); +#if defined XSHOGI + printz ("Clocks: %ld %ld\n",TimeControl.clock[black]*10,TimeControl.clock[white]*10); +#endif +} + +#ifdef DEBUG +void +ChangeDbLev (void) +{ + printz (CP[146]); + scanz ("%hd", &debuglevel); +} + +#endif /* DEBUG */ + +void +ChangeSearchDepth (void) +{ + printz ("depth= "); + scanz ("%hd", &MaxSearchDepth); + TCflag = !(MaxSearchDepth > 0); +} + +void +ChangeHashDepth (void) +{ + printz ("hashdepth= "); + scanz ("%hd", &HashDepth); + printz ("MoveLimit= "); + scanz ("%hd", &HashMoveLimit); +} + +void +SetContempt (void) +{ + printz ("contempt= "); + scanz ("%hd", &contempt); +} + +void +ChangeXwindow (void) +{ + printz ("xwndw= "); + scanz ("%hd", &xwndw); +} + +void +ShowPostnValue (short int sq) + +/* + * must have called ExaminePosition() first + */ + +{ + short score; + score = ScorePosition (color[sq]); + if (color[sq] != neutral){ +#if defined SAVE_SVALUE + printz ("???%c ", (color[sq] == white)?'b':'w');} +#else + printz ("%3d%c ", svalue[sq],(color[sq] == white)?'b':'w');} +#endif + else + printz(" * "); +} + +void +DoDebug (void) +{ + short c, p, sq, tp, tc, tsq, score,j,k; + char s[40]; + + ExaminePosition (opponent); + ShowMessage (CP[65]); + scanz ("%s", s); + c = neutral; + if (s[0] == CP[9][0] || s[0] == CP[9][1]) /* w W*/ c = black; + if (s[0] == CP[9][2] || s[0] == CP[9][3]) /*b B*/ c = white; + for (p = king; p > no_piece; p--) + if ((s[1] == pxx[p]) || (s[1] == qxx[p])) break; + if(p > no_piece) + for(j=(NO_ROWS-1);j>=0;j--){ + for(k=0;k<(NO_COLS);k++){ + sq=j*(NO_COLS)+k; + tp = board[sq]; + tc = color[sq]; + board[sq] = p; + color[sq] = c; + tsq = PieceList[c][1]; + PieceList[c][1] = sq; + ShowPostnValue (sq); + PieceList[c][1] = tsq; + board[sq] = tp; + color[sq] = tc; + } + printz("\n"); + } + score = ScorePosition (opponent); + for(j=(NO_ROWS-1);j>=0;j--){ + for(k=0;k<(NO_COLS);k++){ + sq=j*(NO_COLS)+k; + if (color[sq] != neutral){ +#if defined SAVE_SVALUE + printz ("%?????%c ", (color[sq] == white)?'b':'w');} +#else + printz ("%5d%c ", svalue[sq],(color[sq] == white)?'b':'w');} +#endif + else + printz(" * "); + } + printz("\n"); + } + printz("stage = %d\n",stage); + printz (CP[103], score, + mtl[computer], pscore[computer], GameType[computer], + mtl[opponent], pscore[opponent], GameType[opponent]); +} + +void +DoTable (short table[NO_SQUARES]) +{ + short sq,j,k; + ExaminePosition (opponent); + for(j=(NO_ROWS-1);j>=0;j--){ + for(k=0;k=0;j--){ + for(k=0;k + ccommand(&argv); +#endif + +#if defined EXTLANGFILE + InitConst (Lang); +#endif + + Initialize_data(); + + for (sq = 0; sq < NO_SQUARES; sq++ ) { + board[sq] = no_piece; + color[sq] = neutral; + } + + ClearCaptured (); + + for (side = 0; side <= 1; side++) + PieceCnt[side] = -1; + +#ifdef TEST_DISTANCE + + strcpy(s,"g6i k5i g4i p9g p8g r* s3h p7g b8h B* S5f"); + + if ( string_to_board_color (s) ) + { + printf("ERROR IN string_to_board_color"); + exit(1); + } + else + { + UpdateDisplay (0, 0, 1, 0); + } + + d = pattern_distance (black, &pattern); + + printf("distance = %d\n", d); + +#endif + + ReadOpeningSequences (&max_pattern_data); + WriteOpeningSequences (max_pattern_data); + +#ifdef DEBUG + GetOpeningPatterns (&max_opening_sequence); + ShowOpeningPatterns (max_opening_sequence); +#endif + +} + + diff --git a/src/pattern.c b/src/pattern.c new file mode 100644 index 0000000..3fa8b3d --- /dev/null +++ b/src/pattern.c @@ -0,0 +1,1002 @@ +/* + * pattern.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "gnushogi.h" + +#if defined DEBUG && !defined EXTPATTERNFILE +/* #define DEBUG_PATTERN */ +/* #define TEST_PATTERN */ +#endif + + +#ifdef DEBUG_PATTERN +#include +#endif + + +#include "pattern.h" + + +#ifdef EXTPATTERNFILE + +#define MAX_PATTERN_DATA 5000 + +small_short pattern_data[MAX_PATTERN_DATA]; + +#define MAX_OPENING_SEQUENCE 20 +#define MAX_PATTERN 200 + +#else + +/* constants and pattern_data are generated by "pat2inc" */ + +#include "pattern.inc" + +#endif + +struct Pattern_rec Pattern[MAX_PATTERN]; +struct OpeningSequence_rec OpeningSequence[MAX_OPENING_SEQUENCE]; + + + +#if defined DEBUG || defined DEBUG_EVAL +static small_ushort sequence_id; +#endif + + + +short ValueOfOpeningName (char *name) +{ + short i; + i = (name[0] == 'C') ? 0 : 100; + switch ( name[7] ) { + case 'S' : i += 10; break; + case 'R' : i += 20; break; + case 'U' : i += 30; break; + default : i += 40; break; + } + switch ( name[9] ) { + case 'S' : i += 1; break; + case 'R' : i += 2; break; + case 'U' : i += 3; break; + default : i += 4; break; + } + return(i); +} + + +void NameOfOpeningValue (short i, char *name) +{ + if ( i < 100 ) + strcpy(name,"CASTLE_?_?"); + else { + strcpy(name,"ATTACK_?_?"); + i -= 100; + } + switch ( i / 10 ) { + case 1 : name[7] = 'S'; break; + case 2 : name[7] = 'R'; break; + case 3 : name[7] = 'U'; break; + default : name[7] = '*'; break; + } + switch ( i % 10 ) { + case 1 : name[9] = 'S'; break; + case 2 : name[9] = 'R'; break; + case 3 : name[9] = 'U'; break; + default : name[9] = '*'; break; + } +} + + +#ifdef EXTPATTERNFILE + +char *patternfile = PATTERNFILE; + +#define is_digit(c) ((c) >= '0' && (c) <= '9') +#define is_alfa(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +#define eos(s) (*s == '\0' || *s == '\n') + + +/* skip blanks and comments in brackets */ + +static void skipbb(char **s) + { while (**s == ' ' || **s == '|' || **s == '[') { + if ( **s == '[' ) + while (**s != ']') (*s)++; + (*s)++; + } \ + } + +/* skip unsigned numbers */ + +static void skipi(char **s) + { + while ( is_digit(**s) ) + (*s)++; + skipbb(s); + } + + +static +short +ScanPiece (char **s, small_short *side, small_short *piece, small_short *square) +{ + short isp, isw, c, r; + + /* determine promotion status */ + if ( **s == '+' ) + isp = true, (*s)++; + else + isp = false; + /* determine side and piece */ + for (c = 0; c < NO_PIECES; c++) + if ((isw = (**s == pxx[c])) || **s == qxx[c]) + { + *piece = isp ? promoted[c] : unpromoted[c]; + *side = isw; + (*s)++; + break; + } + if (c == NO_PIECES) + return(1); + if ( **s == '*' ) + { + /* piece is captured */ + (*s)++; + *square = NO_SQUARES + *piece; + } + else + { + /* determine column */ + for (c = 0; c < NO_COLS; c++) + if (**s == cxx[c]) + { + (*s)++; + break; + } + if (c >= NO_COLS) + return(1); + /* determine row */ + for (r = 0; r < NO_ROWS; r++) + if (**s == rxx[r]) + { + (*s)++; + break; + } + if (r >= NO_ROWS) return(1); + /* determine square */ + *square = r*NO_COLS + c; + } + skipbb(s); + return(0); +} + + +static +short +ScanPattern (char *s, short *pindex) +{ + small_short side, piece, square; + skipbb(&s); /* skip blanks and comments */ + while ( is_digit(*s) ) { + pattern_data[(*pindex)++] = atoi(s); + skipi(&s); + } + pattern_data[(*pindex)++] = END_OF_LINKS; + skipbb(&s); + while ( !eos(s) ) { + if ( ScanPiece(&s, &side, &piece, &square) ) { + return(1); + } else { + pattern_data[(*pindex)++] = piece; + pattern_data[(*pindex)++] = (side ? -square : square); + } + } + pattern_data[(*pindex)++] = END_OF_FIELDS; + return(0); +} + + +void +ReadOpeningSequences (short *pindex) + +{ + FILE *fd; + char s[256]; + short max_pattern = 0; + short max_opening_sequence = 0; + + if ( (fd = fopen (patternfile, "r")) == NULL ) + fd = fopen ("gnushogi.pat", "r"); + + if ( fd != NULL ) { + *pindex = 0; + while ( fgets (s, 256, fd) != NULL ) + { + if ( *s == '#' ) { + /* comment, skip line */ + } else if ( is_alfa(*s) ) { + if ( max_opening_sequence++ > 0 ) { + pattern_data[(*pindex)++] = END_OF_PATTERNS; + } + pattern_data[(*pindex)++] = ValueOfOpeningName(s); + } else { + if ( ScanPattern(s,pindex) ) { + ShowMessage("error in pattern sequence..."); + exit(1); + } else { + max_pattern++; + } + } + } + pattern_data[(*pindex)++] = END_OF_PATTERNS; + pattern_data[(*pindex)++] = END_OF_SEQUENCES; +#if defined NONDSP || defined MSDOS + sprintf(s, "Pattern: %d bytes for %d sequences with %d patterns.\n", + *pindex, max_opening_sequence, max_pattern); + ShowMessage(s); +#endif + fclose(fd); + } +#if defined NONDSP || defined MSDOS + else { + sprintf(s, "no pattern file '%s'",patternfile); + ShowMessage(s); + } +#endif +} + + +void +WriteOpeningSequences (short pindex) +{ + FILE *fd; + short n = 0; + short max_pattern = 0; + short max_opening_sequence = 0; + + fd = fopen ("pattern.inc", "w"); + fprintf(fd,"#define MAX_PATTERN_DATA %d\n\n",pindex); + fprintf(fd,"small_short pattern_data[MAX_PATTERN_DATA] =\n{\n"); + do { + fprintf(fd," %d,\n",pattern_data[n++]); + do { + fprintf(fd," "); + /* write links */ + while ( pattern_data[n] != END_OF_LINKS ) { + fprintf(fd,"%d, ",pattern_data[n++]); + }; + fprintf(fd,"%d, ",pattern_data[n++]); + /* write pattern */ + do { + fprintf(fd,"%d,",pattern_data[n++]); + } while ( pattern_data[n] != END_OF_FIELDS ); + fprintf(fd,"%d,\n",pattern_data[n++]); + max_pattern++; + } while ( pattern_data[n] != END_OF_PATTERNS ); + fprintf(fd," %d,\n",pattern_data[n++]); + max_opening_sequence++; + } while ( pattern_data[n] != END_OF_SEQUENCES ); + fprintf(fd," %d\n};\n",pattern_data[n++]); +#ifdef DEBUG_PATTERN + assert(n == pindex); +#endif + fprintf(fd,"\n#define MAX_OPENING_SEQUENCE %d\n",max_opening_sequence); + fprintf(fd,"\n#define MAX_PATTERN %d\n",max_pattern); + fclose(fd); +} + + +#endif + + + +void +GetOpeningPatterns (short *max_opening_sequence) + +{ + short pindex = 0; + short os = 0; + short p = 0; + short i; + + do { + OpeningSequence[os].opening_type = pattern_data[pindex++]; + OpeningSequence[os].first_pattern[0] = p; + for ( i=1; ipiece = pattern_data[i]; + field->square = pattern_data[i+1]; + if ( field->square < 0 ) { + field->square = -(field->square); + field->side = white; + } else { + field->side = black; + } +} + + + +short +piece_to_pattern_distance + (short side, short piece, short pside, short pattern) + +/* + * Determine the minimum number of moves from the current position + * to a specific pattern for a specific piece. + * Consider the "side" piece of the pattern. + * The pattern should match for "pside". + */ +{ + short nP, P[4], nB, B[4]; /* at most 4 pieces of same kind */ + short nC, i, j, r, dd, occupied, mindd, c[4], d[4]; + short c1 = side ^ pside; /* a "side" patternfield must match a "c1" piece on board */ + + /* + * If pside == white, a black piece in the pattern should match + * a white piece on board, and vice versa. Furthermore, if + * pside == white, reversed pattern should match board. + */ + + /* special pawn handling */ + + if ( piece == pawn ) { + mindd = occupied = 0; + for ( i = Pattern[pattern].first_field; pattern_data[i] != END_OF_FIELDS; i += 2 ) { + struct PatternField field; + set_field(i, &field); + if ( (field.side == side) && (field.piece == pawn) ) { + short t = field.square; + short pcol = column(t); + dd = CANNOT_REACH; + if ( PawnCnt[c1][(side == c1) ? pcol : (8 - pcol)] ) { + /* there is a pawn on the column */ + for ( j = 0; j <= PieceCnt[c1]; j++) { + short sq = (short)PieceList[c1][j]; + if ( board[sq] == pawn ) { + if ( pside == white ) sq = NO_SQUARES - 1 - sq; + if ( column(sq) == pcol ) { + dd = piece_distance (side, pawn, sq, t); +#ifdef TEST_PATTERN + printf("update %d pawn from %d to %d is %d\n", side, sq, t, dd); +#endif + break; + } + } + } + } else { + /* there is no pawn on the column; drop possible? */ + if ( Captured[c1][pawn] ) { + dd = 1; +#ifdef TEST_PATTERN + printf("update %d pawn drop to %d is %d\n", side, t, dd); +#endif + } + } + if ( dd >= 0 ) { + /* Increment distance if pattern field is occupied */ + short psq, pc; + if ( pside == black ) { + psq = t; + pc = field.side; + } else { + psq = (NO_SQUARES - 1 - t); + pc = ~field.side; + } + if ( (color[psq] == pc) && (board[psq] != pawn) ) { +#ifdef TEST_PATTERN + printf("square %d is occupied\n", psq); +#endif + ++occupied; + } + mindd += dd; + } else { + return (CANNOT_REACH); + } + } + } + return (mindd + occupied); + } + + /* + * Determine list of "side" "piece"s in pattern. + */ + + for ( occupied = nP = 0, i = Pattern[pattern].first_field; pattern_data[i] != END_OF_FIELDS; i+=2 ) { + struct PatternField field; + set_field(i, &field); + if ( (field.side == side) && (field.piece == piece) ) { + short psq, pc; + P[nP] = field.square; +#ifdef TEST_PATTERN + printf("pattern %d piece %d on square %d\n",side,piece,P[nP]); +#endif + nP++; + /* Increment distance if pattern field is occupied */ + if ( pside == black ) { + psq = field.square; + pc = field.side; + } else { + psq = (NO_SQUARES - 1 - field.square); + pc = field.side ^ 1; + } + if ( (color[psq] == pc) && (board[psq] != field.piece) ) { +#ifdef TEST_PATTERN + printf("square %d is occupied\n", psq); +#endif + ++occupied; + } + } + } + + if ( nP == 0 ) + return (0); + +#ifdef TEST_PATTERN + printf("finding in pattern %d pieces %d of side %d\n", nP, piece, side); +#endif + + /* + * Determine list of "side ^ pside" "piece"s captured or on board. + */ + + for ( nB = 0; nB < Captured[c1][piece]; nB++ ) + B[nB] = NO_SQUARES + piece; + + for ( i = 0; i <= PieceCnt[c1]; i++ ) { + short sq = PieceList[c1][i]; + if ( board[sq] == piece ) { + B[nB] = (pside == black) ? sq : (NO_SQUARES - 1 - sq); +#ifdef TEST_PATTERN + printf("%d piece %d on square %d\n",side,piece,B[nB]); +#endif + nB++; + } + } + +#ifdef TEST_PATTERN + printf("found on board %d pieces %d of side %d\n", nB, piece, side); +#endif + + if ( nP > nB ) { + return (CANNOT_REACH); + } + + /* Determine best assignment from board piece to pattern piece */ + + r = 0; c[0] = -1; mindd = CANNOT_REACH; + + while ( (r >= 0) && (mindd != 0) ) { + + if ( ++c[r] == nB ) { + r--; + } else { + for ( i = 0; i < r; i++ ) + if ( c[i] == c[r] ) + break; + if ( i == r ) { + d[r] = piece_distance (side, piece, B[c[r]], P[r]); +#ifdef TEST_PATTERN + printf("update d[%d] from %d to %d is %d\n", r, B[c[r]], P[r], d[r]); +#endif + if ( d[r] < 0 ) { + /* r--; */ + } else { + if ( ++r == nP ) { + for (dd = i = 0; i < nP; i++) + dd += d[i]; + if ( (dd < mindd) || (mindd < 0) ) { + mindd = dd; +#ifdef TEST_PATTERN + printf("update min %d\n", mindd); +#endif + } + r--; + } else + c[r] = -1; + } + } + } + + } + + if ( mindd < 0 ) + return (CANNOT_REACH); + else + return (mindd + occupied); + +} + + +short +pattern_distance (short pside, short pattern) + +/* + * Determine the minimum number of moves for the pieces from + * the current position to reach a pattern. + * The result is CANNOT_REACH, if there is no possible sequence + * of moves. + */ + +{ + short side, piece, d, n; + +#ifdef TEST_PATTERN + printf("\nchecking pattern %d for pside=%d\n\n",pattern,pside); +#endif + + for ( n = side = 0; side <= 1 && n >= 0; side++ ) + for ( piece = pawn; piece <= king; piece++ ) { + d = piece_to_pattern_distance (side, piece, pside, pattern); + if ( d < 0 ) { + n = CANNOT_REACH; break; + } else + n += d; + } + +#ifdef TEST_PATTERN + printf("\ndistance to pattern is %d\n\n",n); +#endif + + return (n); + +} + + +short +board_to_pattern_distance + (short pside, short osequence, short pmplty, short GameCnt) + +/* + * Determine the maximal difference of the number of moves from the pattern + * to the initial position and to the current position. + * Differences are weighted, i.e. the more closer a position is to a pattern + * the more valuable is a move towards the pattern. + * Patterns, which are at least "pmplty" halfmoves away, are not counted. + */ + +{ + short i, d, dist, diff, weighted_diff; + short maxdiff = 0, max_weighted_diff = 0; + short pattern; + +#ifdef DEBUG_EVAL + if ( debug_eval ) { + char name[MAX_NAME]; + NameOfOpeningValue(OpeningSequence[osequence].opening_type,name); + fprintf(debug_eval_file,"board to %s pattern distance pside=%s, pmplty=%d, GameCnt=%d\n", + name, ColorStr[pside], pmplty, GameCnt); + } +#endif + + for ( i=0; i= 0 ) { +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file," initially reachable in %d steps\n",d); +#endif + if ( pmplty > d ) + { + dist = pattern_distance (pside, pattern); + if ( dist >= 0 ) + { + /* "dist" is the distance of the current board position to the pattern. + * "d - dist" is the difference between the current distance and the + * initial distance. Compute "diff" as the weighted difference. + */ +#ifdef DEBUG_EVAL + if ( debug_eval ) { + fprintf(debug_eval_file," now reachable in %d steps\n",dist); + DisplayPattern(debug_eval_file,Pattern[pattern].first_field); + } +#endif + /* try to reach the nearest pattern */ + weighted_diff = (diff = (d - dist)) * (pmplty - d); + if ( weighted_diff > max_weighted_diff ) { +#ifdef COUNT_DIFF + maxdiff = diff; +#else + maxdiff = weighted_diff; +#endif + max_weighted_diff = weighted_diff; +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"current maximum gain %d\n",maxdiff); +#endif + } +#ifdef DEBUG_EVAL + else { + if ( debug_eval ) + fprintf(debug_eval_file,"gain %d\n",diff); + } +#endif + /* A reached pattern should not be considered in the future (if GameCnt >= 0) */ + if ( dist == 0 && GameCnt >= 0) + { + Pattern[pattern].reachedGameCnt[pside] = GameCnt; +#ifdef DEBUG_EVAL + if ( debug_eval ) + fprintf(debug_eval_file,"pattern reached in move %d\n",GameCnt); +#endif + } + } +#ifdef DEBUG_EVAL + else + if ( debug_eval ) + fprintf(debug_eval_file," now unreachable\n"); +#endif + } +#ifdef DEBUG_EVAL + else + { + if ( debug_eval ) + fprintf(debug_eval_file," beyond %d steps\n",pmplty); + } +#endif + } +#ifdef DEBUG_EVAL + else { + if ( debug_eval ) + fprintf(debug_eval_file, + (d == NOT_TO_REACH) ? " not to reach\n" : + (d == IS_REACHED) ? " is reached\n" : + (d == IS_SUCCESSOR) ? " is successor\n" : " cannot reach\n"); + } +#endif + } + + return (maxdiff); + +} + + +void +DisplayPattern (FILE *fd, short n) + +{ + small_short pboard[NO_SQUARES], pcolor[NO_SQUARES]; + short sq, i, r, c; + + for (sq = 0; sq < NO_SQUARES; sq++) + { + pboard[sq] = no_piece; + pcolor[sq] = neutral; + } + + for (i = n; pattern_data[i] != END_OF_FIELDS; i += 2) + { + struct PatternField field; + set_field(i,&field); + pboard[field.square] = field.piece; + pcolor[field.square] = field.side; + } + + for (r = NO_ROWS-1; r >= 0; r--) + { + for (c = 0; c < NO_COLS; c++) + { + sq = r*NO_COLS + c; + i = pboard[sq]; + if ( i == no_piece ) + fprintf(fd," -"); + else + fprintf(fd,"%c%c",is_promoted[i]?'+':' ',pcolor[sq]?pxx[i]:qxx[i]); + } + fprintf(fd,"\n"); + } + + fprintf(fd,"\n"); + +} + + + + +static +void +VisitReachable (int pside, short osequence, int k, int n, int remove) +{ + short i,j; + short pattern; + +#ifdef DEBUG_PATTERN + printf("visit reachable %d %d %s\n",k,n,remove?"remove":""); +#endif + + /* Adjust to sequence pattern n */ + for (i=0,pattern=OpeningSequence[osequence].first_pattern[k]; i= 0 ) { + Pattern[pattern].distance[pside] = IS_SUCCESSOR; +#ifdef DEBUG_PATTERN + printf("removing %d\n",n); +#endif + } + +} + + +/* simplified matching for opening type names */ + +#define match_char(a,b) (a == b || (a == '*' && b != 'U') || (b == '*' && a != 'U')) +#define match_name(a,b,l) (l>8 && match_char(a[0],b[0]) && match_char(a[7],b[7]) && match_char(a[9],b[9])) + + +short locate_opening_sequence(short pside, char *s, short GameCnt) + +{ + short i,j,k, os, removed, d; +#ifdef DEBUG_PATTERN + short n = 0, m = 0; +#endif + short l = strlen(s); + short check_visited[MAX_SEQUENCE]; + char name[MAX_NAME], name2[MAX_NAME]; + + /* + * Look for opening pattern name in the list of opening patterns. + */ + + name[0] = '\0'; + for ( i = 1,os = 0; os=MAX_OPENING_SEQUENCE ) + return(END_OF_SEQUENCES); + else + for ( ; i= 0 && GameCnt >= Pattern[k].reachedGameCnt[pside] ) { + Pattern[k].distance[pside] = IS_REACHED; +#ifdef DEBUG_PATTERN + printf("pattern %d removed because reached at GameCnt %d below current %d\n", + k,Pattern[k].reachedGameCnt[pside],GameCnt); +#endif + } + if ( Pattern[k].reachedGameCnt[pside] >= GameCnt ) + Pattern[k].reachedGameCnt[pside] = MAXMOVES; + } + + /* + * Remove reachable patterns from search, which are successors of + * reachable patterns. So, only the next pattern of a pattern sequence + * is observed. + */ + + for ( i=0; i= 0 ) { + for (j=Pattern[k].first_link; pattern_data[j]!=END_OF_LINKS; j++) { +#ifdef DEBUG_PATTERN + printf("removing successors for link %d\n",pattern_data[j]); +#endif + VisitReachable(pside,os,i,pattern_data[j],true); + } + } + + /* + * Look, whether there is still a reachable pattern. + */ + + for ( i=0; i= 0 ) + { +#ifdef DEBUG_PATTERN + for ( i=n=m=0; i= 0 ) + m++; + printf("%d reachable %s patterns out of %d patterns\n", + m,ColorStr[pside],n); +#endif + return(os); + } + +#ifdef DEBUG_PATTERN + printf("all %s patterns out of %d patterns (%d reachable) removed\n", + ColorStr[pside],n,m); +#endif + + return (END_OF_SEQUENCES); +} + + +void update_advance_bonus (short pside, short os) +{ + struct PatternField field; + short i, j, k, d; + + for ( j=0; j= 0 ) + { + for ( i = Pattern[k].first_field; pattern_data[i]!=END_OF_FIELDS; i+=2 ) { + set_field(i,&field); + if ( field.side == black ) { + short square = (pside == black) + ? field.square + : NO_SQUARES - 1 - field.square; + (*Mpiece[field.piece])[pside][square] += ADVNCM[field.piece]; + } + } + } +} diff --git a/src/pattern.h b/src/pattern.h new file mode 100644 index 0000000..5fa304b --- /dev/null +++ b/src/pattern.h @@ -0,0 +1,120 @@ +/* + * pattern.h - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* #define TEST_PATTERN */ +/* #define DEBUG_PATTERN */ + + +#define MAX_NAME 16 /* maximum length of opening name */ +#define MAX_SEQUENCE 4 /* maximum number of sequences for an opening type */ + + +#define CANNOT_REACH (-1) +#define NOT_TO_REACH (-2) +#define IS_REACHED (-3) +#define IS_SUCCESSOR (-4) + +#define END_OF_SEQUENCES (-1) +#define END_OF_PATTERNS (-2) +#define END_OF_LINKS (-3) +#define END_OF_FIELDS (-4) + + struct PatternField { + short side; + short piece; + short square; + }; + + + struct Pattern_rec { + small_short visited; + small_short distance[2]; + short reachedGameCnt[2]; + short first_link; + short first_field; + short next_pattern; + }; + + + struct OpeningSequence_rec { + short opening_type; + short first_pattern[MAX_SEQUENCE]; + }; + + +extern struct OpeningSequence_rec OpeningSequence[]; +extern struct Pattern_rec Pattern[]; + + + +extern + short + piece_to_pattern_distance + (short side, short piece, short pside, short pattern); + +extern + short + pattern_distance (short pside, short pattern); + +extern + short + board_to_pattern_distance + (short pside, short osequence, short pmplty, short GameCnt); + +extern + short locate_opening_sequence(short pside, char *s, short GameCnt); + +extern + void + DisplayPattern (FILE *fd, short first_field); + +extern + void update_advance_bonus (short pside, short os); + +extern + void + GetOpeningPatterns (short *max_opening_sequence); + +extern + void + ShowOpeningPatterns (short max_opening_sequence); + + +extern short ValueOfOpeningName (char *name); + +extern void NameOfOpeningValue (short i, char *name); + + +#ifdef EXTPATTERNFILE + +extern void ReadOpeningSequences (short *pindex); + +extern void WriteOpeningSequences (short pindex); + +#endif + + diff --git a/src/pattern.inc b/src/pattern.inc new file mode 100644 index 0000000..802219f --- /dev/null +++ b/src/pattern.inc @@ -0,0 +1,166 @@ +#define MAX_PATTERN_DATA 2102 + +small_short pattern_data[MAX_PATTERN_DATA] = +{ + 11, + 5, -3, 1,29,1,19,6,10,4,12,5,3,1,-46,1,-60,-4, + 6, -3, 1,19,1,29,4,10,6,20,1,-37,1,-51,-4, + 8, -3, 1,19,1,29,4,20,1,21,1,22,5,11,14,12,5,13,-4, + 5, -3, 6,10,1,19,1,29,4,20,5,11,14,3,-4, + 5, -3, 14,4,5,3,5,21,4,11,6,10,1,19,1,29,1,30,-4, + 8, -3, 14,3,6,2,5,11,4,20,1,19,1,29,-4, + 7, -3, 14,3,4,10,5,11,5,13,1,19,6,20,1,29,1,30,1,31,-4, + 8, -3, 14,3,5,11,6,12,5,13,1,19,4,20,1,29,1,30,1,31,-4, + 9, 10, -3, 14,2,5,11,1,19,1,29,4,20,1,30,1,31,5,21,-4, + 11, -3, 14,10,5,11,1,27,1,19,1,29,1,30,4,20,5,21,1,-45,-4, + -3, 14,2,5,10,1,18,1,19,4,20,5,21,1,29,1,30,1,-36,-4, + -3, 2,0,3,1,14,10,5,11,4,20,1,19,1,27,1,29,-4, + 13, -3, 6,20,4,-65,-4, + 6, -3, 6,20,4,10,5,11,4,-46,-4, + 2, -3, 4,20,5,11,14,12,5,13,-4, + 8, -3, 14,2,5,11,5,21,-4, + 7, -3, 14,3,5,11,6,12,5,13,4,20,-4, + 11, -3, 2,0,3,1,14,10,5,11,4,20,-4, + 6, -3, 14,3,4,10,5,11,5,13,1,19,6,20,-4, + -2, + 111, + 1, 2, -3, 1,22,1,23,1,24,1,34,1,26,7,16,4,6,-4, + 3, -3, 1,22,1,23,1,24,1,34,4,14,7,16,3,7,-4, + 4, -3, 4,15,1,23,1,24,1,34,7,16,-4, + 5, 6, 7, -3, 4,14,1,23,1,33,1,34,1,26,7,16,3,7,-4, + 12, 14, 15, 17, -3, 1,33,1,43,4,34,1,35,7,16,3,7,2,8,-4, + 12, -3, 3,7,7,16,4,24,1,33,1,43,1,44,1,-53,-4, + 9, 11, -3, 2,8,7,16,4,23,3,24,1,32,1,33,1,34,1,44,1,-62,-4, + 8, -3, 4,14,1,31,1,23,3,24,1,33,1,34,7,16,2,26,-4, + -3, 4,14,1,31,1,23,3,24,1,33,1,34,7,17,2,26,-4, + 10, -3, 4,23,1,32,3,24,3,33,7,16,2,26,1,44,-4, + -3, 4,23,1,32,3,24,3,33,7,17,2,26,1,44,-4, + -3, 4,31,1,22,1,32,1,33,3,24,7,16,1,43,1,35,2,8,-4, + 13, -3, 3,7,4,24,1,33,1,43,2,26,7,16,-4, + -3, 3,7,4,24,1,33,1,43,2,26,7,17,-4, + 16, -3, 3,7,2,8,7,16,1,43,1,33,4,42,-4, + 16, -3, 3,7,2,8,7,16,1,43,1,42,4,34,-4, + -3, 4,42,1,52,7,16,-4, + -3, 4,44,1,52,7,16,-4, + -2, + 12, + 1, 2, -3, 5,3,5,13,14,4,6,10,1,29,4,2,3,1,2,0,-4, + 3, -3, 1,27,2,0,3,1,6,10,14,11,5,3,5,13,1,19,1,29,1,21,1,31,-4, + 4, -3, 2,0,3,1,4,2,5,3,5,13,14,12,6,10,1,19,1,21,1,29,-4, + 7, 8, -3, 2,0,3,1,5,3,6,10,14,11,4,12,5,13,1,27,1,19,1,29,1,21,1,31,-4, + 5, -3, 2,0,3,1,4,2,5,3,5,13,14,11,6,10,1,19,1,21,1,29,1,22,-4, + 6, -3, 2,9,14,10,3,1,4,2,5,3,6,20,1,18,1,19,1,29,-4, + -3, 14,0,2,9,4,10,5,11,5,2,1,19,6,20,1,29,1,21,-4, + -3, 2,0,3,1,14,10,5,11,1,27,1,19,6,20,5,21,1,29,1,30,-4, + 9, -3, 2,0,3,1,6,10,14,11,5,3,5,13,4,20,1,38,1,21,4,22,1,31,1,-56,-4, + -3, 2,0,3,1,14,10,5,11,6,20,5,21,4,22,4,29,1,30,1,31,1,37,1,38,-4, + 1, -3, 2,0,3,1,6,10,14,11,5,3,5,13,-4, + 3, -3, 2,0,3,1,5,3,6,10,14,11,4,12,5,13,-4, + 2, -3, 2,0,3,1,4,2,5,3,5,13,14,12,6,10,-4, + -2, + 112, + 1, 2, 6, -3, 7,16,1,43,-4, + 2, 3, 5, 6, 13, -3, 4,14,7,16,3,7,2,8,1,31,1,33,-4, + 13, -3, 2,8,4,14,7,16,3,24,1,32,1,33,-4, + 4, -3, 2,8,3,7,7,16,4,12,1,24,1,23,4,22,1,40,1,-58,1,-50,-4, + -3, 2,8,3,7,7,16,4,12,1,24,1,23,4,31,1,40,1,-58,-4, + -3, 2,8,6,10,4,20,4,22,1,38,1,-56,-4, + 7, -3, 1,43,1,35,7,16,4,15,-4, + 8, 10, -3, 1,43,1,33,1,35,4,34,7,16,-4, + 9, -3, 1,42,1,43,1,35,4,34,7,16,-4, + -3, 4,42,1,43,1,35,7,16,-4, + -3, 1,43,4,44,1,35,7,16,-4, + 12, -3, 2,26,7,16,-4, + -3, 2,26,7,17,1,53,-4, + 11, -3, 4,23,3,24,7,16,2,8,1,32,1,33,-4, + -2, + 21, + 1, -3, 5,3,5,5,4,6,3,7,2,8,14,14,1,23,1,24,1,25,1,26,-4, + 2, 4, -3, 5,3,5,5,4,6,3,7,2,8,14,16,1,23,1,24,1,25,1,26,-4, + 3, -3, 5,5,4,6,3,7,14,8,5,13,2,17,1,23,1,24,1,25,1,26,-4, + 12, -3, 5,6,3,7,14,8,5,15,4,16,2,17,1,23,1,24,1,25,1,26,-4, + 5, 8, -3, 5,5,3,7,2,8,4,15,14,16,1,24,1,25,1,35,-4, + 6, 9, -3, 5,5,3,7,2,8,5,13,4,15,14,16,1,23,1,24,1,25,1,35,-4, + 7, 10, -3, 5,5,3,7,2,8,4,15,14,16,5,23,1,25,1,32,1,33,1,35,-4, + 11, -3, 3,7,2,8,5,15,14,16,5,23,4,25,1,32,1,33,1,34,1,35,-4, + 5, -3, 5,5,3,7,2,8,4,15,14,16,1,24,1,25,1,35,-4, + 6, -3, 5,5,3,7,2,8,5,13,4,15,14,16,1,23,1,24,1,25,1,35,-4, + 7, -3, 5,5,3,7,2,8,4,15,14,16,5,23,-4, + -3, 3,7,2,8,5,15,14,16,5,23,4,25,-4, + -3, 5,6,3,7,14,8,5,15,4,16,2,17,-4, + -2, + 22, + 1, -3, 2,8,4,6,5,5,5,3,14,15,1,25,1,24,1,23,-4, + 2, -3, 2,8,5,5,4,16,14,15,5,13,1,25,1,24,1,23,-4, + -3, 4,16,14,15,5,14,5,13,1,25,1,24,1,23,-4, + 0, -3, 2,8,4,6,5,5,5,3,14,15,-4, + 1, -3, 2,8,5,5,4,16,14,15,5,13,-4, + 2, -3, 4,16,14,15,5,14,5,13,-4, + -2, + 13, + -3, 1,26,1,43,1,24,1,23,1,22,1,21,1,29,1,19,1,18,3,1,4,2,5,3,14,4,5,5,4,6,3,7,-4, + -3, 1,19,1,29,1,21,5,3,5,13,1,31,-4, + -2, + 113, + 1, 2, -3, 1,34,7,16,-4, + 3, -3, 1,34,4,14,-4, + 6, -3, 1,34,4,15,-4, + 4, 5, -3, 1,34,4,14,1,33,-4, + -3, 1,34,1,32,1,33,4,23,3,24,-4, + -3, 1,43,1,33,4,24,1,44,-4, + 7, -3, 1,43,4,25,1,24,-4, + -3, 1,43,4,34,1,35,1,33,-4, + -2, + 23, + 4, -3, 7,13,14,4,5,5,4,6,-4, + 4, -3, 7,12,14,4,5,5,4,6,-4, + 4, -3, 7,11,14,4,5,5,4,6,-4, + 4, -3, 7,10,14,4,5,5,4,6,-4, + -3, 14,15,5,5,4,6,-4, + -2, + 123, + 1, 2, 3, 4, -3, 1,29,1,30,6,20,-4, + -3, 7,10,1,29,1,30,6,20,4,21,-4, + -3, 7,11,1,29,1,30,6,20,-4, + -3, 7,12,1,29,1,30,6,20,4,21,-4, + -3, 7,13,1,29,1,30,6,20,4,21,-4, + -2, + 33, + 1, -3, 1,24,1,23,1,21,1,29,3,1,4,2,5,3,14,4,5,5,4,6,3,7,-4, + 2, 3, -3, 1,24,1,23,1,30,1,29,6,10,4,2,5,3,14,4,5,5,4,6,-4, + 4, -3, 1,30,1,29,4,11,6,10,-4, + 4, -3, 1,30,1,29,4,12,6,10,-4, + -3, 1,30,1,29,4,12,6,10,1,44,-4, + -2, + -123, + -3, 1,29,-4, + -2, + 124, + 1, 5, 8, 10, -3, 6,20,1,29,1,30,14,4,5,5,4,6,1,25,-4, + 2, -3, 7,10,6,20,1,29,1,30,14,4,5,5,4,6,-4, + 3, 4, -3, 7,10,3,1,5,3,6,20,4,21,1,29,1,30,-4, + -3, 7,10,3,1,5,11,6,20,4,21,1,29,1,30,-4, + -3, 7,10,3,1,5,13,6,20,4,21,1,29,1,30,-4, + 6, 7, -3, 7,11,6,20,1,29,1,30,14,4,5,5,4,6,-4, + -3, 7,11,4,21,5,13,1,19,6,20,1,29,1,30,-4, + -3, 7,11,4,21,1,19,6,20,1,29,1,30,1,31,-4, + 9, -3, 7,12,6,20,4,21,1,29,1,30,14,4,5,5,4,6,-4, + -3, 7,12,3,1,5,3,1,19,6,20,4,21,1,29,1,30,-4, + 11, 13, -3, 7,13,1,19,6,20,4,21,14,4,5,5,4,6,-4, + 12, -3, 7,13,3,1,5,11,1,19,6,20,4,21,1,29,1,30,-4, + -3, 7,4,3,1,1,19,6,20,4,21,4,23,1,29,1,30,-4, + -3, 7,13,3,1,1,19,6,20,4,21,5,23,1,29,1,30,-4, + -2, + 34, + 1, -3, 1,24,1,23,1,21,1,29,3,1,4,2,5,3,14,4,5,5,4,6,3,7,-4, + 2, 3, -3, 1,24,1,23,1,30,1,29,6,10,4,2,5,3,14,4,5,5,4,6,-4, + 4, -3, 1,30,1,29,4,11,6,10,-4, + 4, -3, 1,30,1,29,4,12,6,10,-4, + -3, 1,30,1,29,4,12,6,10,1,44,-4, + -2, + -1 +}; + +#define MAX_OPENING_SEQUENCE 14 + +#define MAX_PATTERN 128 diff --git a/src/search.c b/src/search.c new file mode 100644 index 0000000..d3c7289 --- /dev/null +++ b/src/search.c @@ -0,0 +1,1787 @@ +/* + * search.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software + * Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 + * GNU Shogi; see the file COPYING. If not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "gnushogi.h" +#ifdef DEBUG +#include +#endif +#if !defined OLDTIME && defined HASGETTIMEOFDAY +double pow(); +#endif +short background = 0; +static short int DepthBeyond; +unsigned short int PrVar[MAXDEPTH]; +extern short int recycle, ISZERO; +#ifdef NULLMOVE +short int null; /* Null-move already made or not */ +short int PVari; /* Is this the PV */ +#endif +#ifdef DEBUG40 +extern int whichway; +#endif +#ifdef DEBUG +unsigned short DBLINE[MAXDEPTH]; +struct leaf far *dbptr; + +#endif + + + +#ifdef DEBUG_EVAL +extern short debug_eval; +extern FILE *debug_eval_file; +#endif + + +short int zwndw; + + +#ifdef DEBUG41 +void +debug41 (short int score, short unsigned int xxx[], char ch) +{ + register int i; + FILE *D; + int r, c, l; + struct leaf far *xnode; + + D = fopen ("/tmp/DEBUG", "a+"); + if (D == NULL) + { + perror ("opening D"); + } + + ElapsedTime (2); + fprintf (D, "%2d%c %6d %4ld %8ld ", Sdepth, ch, score, et / 100, NodeCnt); + + for (i = 1; xxx[i]; i++) + { + if ((i > 1) && (i % 8 == 1)) + fprintf (D, "\n "); + algbr ((short) (xxx[i] >> 8), (short) (xxx[i] & 0xFF), false); + fprintf (D, "%5s ", mvstr[0]); + } + fprintf (D, "\n"); + fclose (D); +} + +#endif + + + + +/* ............ MOVE GENERATION & SEARCH ROUTINES .............. */ + + + + +short int +repetition () + +/* Check for draw by fourfold repetition + * (same side, same captures, same board). + * WARNING: this is not save yet due to possible hash collisions. + */ + +{ + short int i, cnt = 0; + +#ifndef NOREPETITION + struct GameRec far *g; + + if (GameCnt > Game50 + 6) + { + for (i = GameCnt-1; i >= Game50; i -= 2) + { + g = &GameList[i]; + if ( g->hashkey == hashkey && g->hashbd == hashbd ) + { + cnt++; + } + } + } + +#endif + + return (cnt); +} + + +int plyscore, globalscore; +int +pick (short int p1, short int p2) + +/* + * Find the best move in the tree between indexes p1 and p2. Swap the best + * move into the p1 element. + * + */ +{ + register struct leaf far *p, *q, *r, *k; + register s0; + struct leaf temp; + + k = p = &Tree[p1]; + q = &Tree[p2]; + s0 = p->score; + for (r = p + 1; r <= q; r++) + if ((r->score) > s0) + { + s0 = (r->score); + p = r; + } + if (p != k) + { + temp = *p; + *p = *k; + *k = temp; + return true; + } + return false; +} + +#ifdef DEBUG +unsigned short trace[MAXDEPTH]; +char traceline[256]; +unsigned short tracelog[MAXDEPTH]; +int tracen = 0; +int traceflag = 0; +int traceply = 0; +#endif +int bookflag = false; +int Jscore = 0; + +/* #define PLYDEBUG */ + +#ifdef PLYDEBUG +static int MaxPly = 0; +static int MaxDepth = 0; +#endif + +int TCcount; +long TCleft = 0; + + + +#ifdef DEBUG4 +static void debug4(short Sdepth, short alpha, short beta, short stage) +{ + if (debuglevel & 4) + { + int j; + + printf ("Sdepth %d alpha %d beta %d stage %d\n", Sdepth, alpha, beta, stage); + for (j = 1; j < 2; j++) + { + int idb; + + for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++) + { + algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags); + printf ("level 4 %d-->%d %s %d %d\n", j, idb, mvstr[0], Tree[idb].score, Tree[idb].width); + } + } + } +} +#endif + + +void +SelectMove (short int side, SelectMove_mode iop) + + +/* + * Select a move by calling function search() at progressively deeper ply + * until time is up or a mate or draw is reached. An alpha-beta window of + * -Awindow to +Bwindow points is set around the score returned from the + * previous iteration. If Sdepth != 0 then the program has correctly + * predicted the opponents move and the search will start at a depth of + * Sdepth+1 rather than a depth of 1. + */ + +{ + static short int i, tempb, tempc, tempsf, tempst, xside, rpt; + static short int alpha, beta, score; + static struct GameRec far *g; + short blocked; + short sqking, in_check, blockable; + +#ifdef PLYDEBUG + MaxPly = 0; + MaxDepth = 0; +#endif + +#ifdef DEBUG + +if ( debuglevel & (512 | 1024) ) { + char b[32]; + short c1,c2,r1,r2,piece; + tracen = 0; + traceflag = false; + traceply = 0; + tracelog[0] = 0; + while ( true ) { + printf( "debug?" ); + gets(b); + if ( b[0] == 'p' ) + traceply = atoi(&b[1]); + else if ( b[0] == '\0' ) + break; + else + { + if ( b[1] = '*' || b[1] == '\'' ) + { + for (piece = pawn; piece <= king; piece++) + if ( b[0] == pxx[piece] || b[0] == qxx[piece] ) + break; + c2 = '9' - b[2]; + r2 = 'i' - b[3]; + if ( side == white ) + piece += NO_PIECES; + trace[++tracen] = ((NO_SQUARES+piece) << 8) | locn (r2, c2); + } + else + { + c1 = '9' - b[0]; + r1 = 'i' - b[1]; + c2 = '9' - b[2]; + r2 = 'i' - b[3]; + trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2); + if ( b[4] == '+' ) + trace[tracen] |= 0x80; + } + } + if (tracen == 0 && traceply > 0) + traceflag = true; + } + +} + +#endif + +#ifdef BOOKTEST + printf("hashbd = %ld (hashkey>>16)|side = %d\n", + hashbd,(hashkey>>16)|side); +#endif + + flag.timeout = false; + flag.back = false; + flag.musttimeout = false; + + xside = side ^ 1; + +#if ttblsz + recycle = (GameCnt % rehash) - rehash; +#endif + + ExaminePosition (side); + + /* if background mode set to infinite */ + if (iop == BACKGROUND_MODE) + { + background = true; + /* if background mode set response time to infinite */ + ResponseTime = 9999999; + } + else + { + player = side; + SetResponseTime (side); + } + +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowResponseTime (); + + ExtraTime = 0; + + score = ScorePosition (side); + +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowSidetoMove (); + +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + SearchStartStuff (side); + +#ifdef HISTORY + array_zero (history, sizeof_history); +#endif + + FROMsquare = TOsquare = -1; + PV = 0; + if (iop == FOREGROUND_MODE) + hint = 0; + +#ifdef DEBUG + { + char buf1[8], buf2[8], buf3[8], buf4[8]; + movealgbr(GameList[GameCnt].gmove,buf1); + movealgbr(PrVar[1],buf2); + movealgbr(PrVar[2],buf3); + movealgbr(PrVar[3],buf4); + printf("gmove: %s PrVar[1]: %s PrVar[2]: %s PrVar[3]: %s\n", + buf1, buf2, buf3, buf4); + } +#endif + + /* + * If the last move was the hint, select the computed answer to the + * hint as first move to examine. + */ + +#if MAXDEPTH > 3 + if ( GameCnt > 0 ) { + SwagHt = (GameList[GameCnt].gmove == PrVar[2]) ? PrVar[3] : 0; + } else +#endif + SwagHt = 0; + +#ifdef DEBUG + { + char buf[8]; + movealgbr(SwagHt,buf); + printf("SwagHt = %s\n", buf); + } +#endif + + for (i = 0; i < MAXDEPTH; i++) + PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0; + + /* set initial window for search */ + + if ( flag.tsume ) { + alpha = -(SCORE_LIMIT+999); + beta = SCORE_LIMIT+999; + } else { + alpha = score - ((computer == white) ? BAwindow : WAwindow); + beta = score + ((computer == white) ? BBwindow : WBwindow); + } + + rpt = 0; + TrPnt[1] = 0; + root = &Tree[0]; + + sqking = PieceList[side][0]; + in_check = (board[sqking] == king) ? SqAtakd(sqking, side^1, &blockable) : false; + + MoveList (side, 1, in_check, blockable); + for (i = TrPnt[1]; i < TrPnt[2]; i++) + if (!pick (i, TrPnt[2] - 1)) + break; + +#ifdef DEBUG_EVAL + if ( debug_eval ) + { short j; + for (j = TrPnt[1]; j < TrPnt[2]; j++) + { + struct leaf far *node = &Tree[j]; + algbr (node->f, node->t, node->flags); + fprintf (debug_eval_file, "%s %s %s %s %d", + mvstr[0], mvstr[1], mvstr[2], mvstr[3],node->score); + if ( node->flags ) + { char s[80]; + FlagString(node->flags, s); + fprintf(debug_eval_file,"%s",s); + } + fprintf (debug_eval_file, "\n"); + } + } +#endif + + /* can I get a book move? */ + + if (flag.regularstart && Book) + { + flag.timeout = bookflag = OpeningBook (&hint, side); + + if (TCflag) + ResponseTime += ResponseTime; + } + + /* zero stats for hash table */ + + reminus = replus = 0; + GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0; + + globalscore = plyscore = score; + Jscore = 0; + zwndw = 20; + +#ifdef DEBUG4 + debug4(Sdepth,alpha,beta,stage); +#endif + + /********************* main loop ********************************/ + + Sdepth = (MaxSearchDepth < (MINDEPTH-1)) ? MaxSearchDepth : (MINDEPTH-1); + + while (!flag.timeout) + { + /* go down a level at a time */ + Sdepth++; +#ifdef NULLMOVE + null = 0; + PVari = 1; +#endif + /* terminate search at DepthBeyond ply past goal depth */ + if ( flag.tsume ) + DepthBeyond = Sdepth; + else +#if defined SLOW_CPU + DepthBeyond = Sdepth + ((Sdepth == 1) ? 3 : 5); +#else + DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11); +#endif + +#if !defined BAREBONES +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowDepth (' '); +#endif + /* search at this level returns score of PV */ + score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt); + + /* save PV as killer */ + for (i = 1; i <= Sdepth; i++) + killr0[i] = PrVar[i]; + + /* low search failure re-search with (-inf,score) limits */ + if (score < alpha) + { +#if !defined BAREBONES + reminus++; +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowDepth ('-'); +#endif + if (TCflag && TCcount < MAXTCCOUNTR) + { +#ifdef HARDTIMELIMIT + ExtraTime += (MAXTCCOUNTR - TCcount) * TCleft; +#else + ExtraTime += (8 * TCleft); +#endif + TCcount = MAXTCCOUNTR - 1; + } + + score = search (side, 1, Sdepth, -(SCORE_LIMIT+999), (SCORE_LIMIT+999), PrVar, &rpt); + } + + /* high search failure re-search with (score, +inf) limits */ + else if (score > beta && !(root->flags & exact)) + { +#if !defined BAREBONES + replus++; +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowDepth ('+'); +#endif + score = search (side, 1, Sdepth, -(SCORE_LIMIT+999), (SCORE_LIMIT+999), PrVar, &rpt); + } + + /**************** out of search ********************************************/ + CheckForTimeout (score, globalscore, Jscore, zwndw); + + /************************ time control ***********************************/ + + /* save PV as killer */ + for (i = 1; i <= Sdepth + 1; i++) + killr0[i] = PrVar[i]; + if (!flag.timeout) + Tscore[0] = score; + /* if (!flag.timeout) */ +/* + for (i = TrPnt[1]+1; i < TrPnt[2]; i++) + if (!pick (i, TrPnt[2] - 1)) + break; +*/ + /* if done or nothing good to look at quit */ + if ((root->flags & exact) || (score < -SCORE_LIMIT)) + flag.timeout = true; + /* find the next best move put below root */ +#ifdef DEBUG13 + if (flag.timeout && !background) + { + FILE *D; + int r, c, l; + struct leaf far *xnode; + + D = fopen ("/tmp/DEBUG", "a+"); + fprintf (D, " %d ply %d sco %d TC %d gl %d cnt %d\n", + Sdepth, plyscore, score, TCcount, + globalpnt, TrPnt[2] - TrPnt[1]); + for (i = 1; tmp[i]; i++) + { + algbr (tmp[i] >> 8, tmp[i] & 0xff, 0); + fprintf (D, "%s ", mvstr[0]); + } + fprintf (D, "\n"); + for (i = 1; PrVar[i]; i++) + { + algbr (PrVar[i] >> 8, PrVar[i] & 0xff, 0); + fprintf (D, "%s ", mvstr[0]); + } + fprintf (D, "\n"); + algbr (root->f, root->t, root->flags); + fprintf (D, "%s ", mvstr[0]); + fprintf (D, "\n"); + fclose (D); + } +#endif + if (!flag.timeout) + { + /* */ +#if !defined NODYNALPHA + Jscore = (plyscore + score) >> 1; +#endif + zwndw = 20 + abs (Jscore / 12); + plyscore = score; + /* recompute search window */ + beta = score + ((computer == white) ? BBwindow : WBwindow); +#if !defined NODYNALPHA + alpha = ((Jscore < score) ? Jscore : score) - ((computer == white) ? BAwindow : WAwindow) - zwndw; +#else + alpha = score - ((computer == white) ? BAwindow : WAwindow); +#endif + } +#if !defined BAREBONES +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowResults (score, PrVar, '.'); +#ifdef DEBUG41 + debug41 (score, PrVar, '.'); +#endif +#endif +#ifdef DEBUG4 + if (debuglevel & 16) + { + int j; + + printf ("Sdepth %d alpha %d beta %d stage %d\n", Sdepth, alpha, beta, stage); + for (j = 1; j < 2; j++) + { + int idb; + + for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++) + { + algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags); + printf ("level 16 %d-->%d %s %d %d %x\n", Sdepth, idb, mvstr[0], Tree[idb].score, Tree[idb].width, Tree[idb].flags); + } + } + } +#endif + } + + /******************************* end of main loop ***********************************/ + + /* background mode */ + if (iop == BACKGROUND_MODE) + { + return; + } + +#ifdef DEBUG4 + debug4(Sdepth,alpha,beta,stage); +#endif + + if (rpt >= 3) + { + root->flags |= draw; + DRAW = CP[101]; /* Repetition */ + } + else + /* if no moves and not in check then mate for shogi (draw for chess) */ +#ifdef notdef + if ((score == -(SCORE_LIMIT+999)) && !(SqAtakd (PieceList[side][0], xside, &blocked))) + { + root->flags |= mate; + DRAW = CP[87]; /* No moves */ + } + else +#endif + if (GameCnt == MAXMOVES) + { + root->flags |= draw; + DRAW = CP[80]; /* Max Moves */ + } + /* not in book so set hint to guessed move for other side */ + if ( !bookflag ) + hint = ((PrVar[1]) ? PrVar[2] : 0); + + /* if not mate or draw make move and output it */ + if (((score > -(SCORE_LIMIT+999)) && (rpt <= 3)) || (root->flags & draw)) + { + MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore); + algbr (root->f, root->t, (short) root->flags); + } + else + { + algbr (0, 0, 0); /* Zero move string when mate. */ + root->score = score; /* When mate, ignore distinctions! + * --SMC */ + } + g = &GameList[GameCnt]; + if ((g->flags & capture) && (g->piece == king)) + { + flag.mate = flag.illegal = true; + } + /* If Time Control get the elapsed time */ + if ( TCflag ) + ElapsedTime (COMPUTE_AND_INIT_MODE); + /* update time control info */ + OutputMove (); + /* if mate set flag */ +#if BESTDEBUG + printf("score=%d\n",score); +#endif + if ((score == -(SCORE_LIMIT+999) || score == (SCORE_LIMIT+998))) + flag.mate = true; + /* add move to game list */ + g->score = score; + g->nodes = NodeCnt; + g->time = (et +50)/100; +/* + g->time = TCcount; +*/ + g->depth = Sdepth; + +#ifdef DEBUG40 + g->d1 = TCcount; + g->d2 = ResponseTime; + g->d3 = ExtraTime; + g->d4 = TCleft; + g->d5 = et; + g->d6 = hint; + g->d7 = whichway; +#endif + + /* update time control info */ + if (TCflag) + { +#if defined XSHOGI + TimeControl.clock[side] -= (et + OperatorTime + 45); + timecomp[compptr] = (et + OperatorTime + 45); +#else + TimeControl.clock[side] -= (et + OperatorTime); + timecomp[compptr] = (et + OperatorTime); +#endif + /* finished our required moves - setup the next set */ + --TimeControl.moves[side]; + } + /* check for end conditions */ + if ((root->flags & draw) /* && flag.bothsides */ ) + { + flag.mate = true; + } + else if (GameCnt == MAXMOVES) + { + flag.mate = true; + } + /* out of move store, you loose */ + else + /* switch to other side */ + player = xside; + /* if mate clear hint */ + if (flag.mate) + hint = 0; + Sdepth = 0; + +} + + +int +search (short int side, + register short int ply, + register short int depth, + short int alpha, + short int beta, + short unsigned int *bstline, + short int *rpt) + +/* + * Perform an alpha-beta search to determine the score for the current board + * position. If depth <= 0 only capturing moves and + * responses to check are generated and searched, otherwise all moves are + * processed. The search depth is modified for check evasions, certain + * re-captures and threats. Extensions may continue for up to 11 ply beyond + * the nominal search depth. + */ + + +{ + register short j, pnt; + short tempb, tempc, tempsf, tempst; + short xside, pbst, score, rcnt, slk, in_check, blockable; + unsigned short mv, nxtline[MAXDEPTH]; + struct leaf far *node, tmp; + short best = -(SCORE_LIMIT+3000); + short bestwidth = 0; + short mustcut; +#ifdef NULLMOVE + short int PVsave; + short int PVarisave; +#endif +#ifdef DEBUG + int xxxtmp; + int tracetmp; +#endif + NodeCnt++; +#ifdef PLYDEBUG + if (ply > MaxPly) { + MaxPly = ply; + printf("ply %d\n",ply); + } + if (depth > MaxDepth) { + MaxDepth = depth; + printf("depth %d\n",depth); + } +#endif + /* look every ZNODE nodes for a timeout */ +#ifdef NULLMOVE + if (!null) { +#endif + if (NodeCnt > ETnodes ) + { + ElapsedTime (COMPUTE_MODE); + if (flag.back) + { + flag.back = false; + flag.timeout = true; + flag.musttimeout = false; + } + else if (TCflag || MaxResponseTime) + { + if ((et >= (ResponseTime + ExtraTime)) && (Sdepth > MINDEPTH) ) + { + /* try to extend to finish ply */ + if (flag.back || (TCflag && TCcount < MAXTCCOUNTX)) + { flag.back = false; + flag.musttimeout = true; + TCcount++; + ExtraTime += TCleft; + } + else + { flag.back = false; + flag.timeout = true; + flag.musttimeout = false; + } + } + } + else if (flag.back) + { + flag.back = false; + flag.timeout = true; + flag.musttimeout = false; + } +#ifdef QUIETBACKGROUND + if (!background) +#endif + ShowResponseTime (); + } + else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH) + { + flag.timeout = true; + flag.musttimeout = false; + } +#ifdef NULLMOVE + } +#endif + + xside = side ^ 1; + score = evaluate (side, ply, alpha, beta, INCscore, &in_check, &blockable); + + /* + * check for possible repitition if so call repitition - rpt is + * repeat count + */ + if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0) + { + *rpt = repetition (); + + /* + * repeat position >3 don't need to return score it's taken + * care of above + */ + if (*rpt == 1) { score /= 3; score *= 2; } + else if (*rpt == 2) score /= 2; + } + else + *rpt = 0; + + /* score > SCORE_LIMIT its a draw or mate */ + if (score > SCORE_LIMIT) + { + bstline[ply] = 0; + return (score); + } + /* Do we need to add depth because of special conditions */ + /* if in check or in capture sequence search deeper */ + /*************************************** depth extensions ***********************************/ + if (depth > 0) + { + /* Allow opponent a chance to check again */ + if (in_check) { + if (depth < 2) depth = 2; + } else if ( flag.rcptr && +#ifdef HARDTIMELIMIT + !flag.timeout && +#endif + (score > alpha) && (score < beta) && (ply > 2) && + CptrFlag[ply - 1] && CptrFlag[ply - 2]) + ++depth; + } + else + { + if (score >= alpha && +#ifdef HARDTIMELIMIT + (in_check || (!flag.timeout && hung[side] > 1 && ply == Sdepth + 1))) +#else + (in_check || (hung[side] > 1 && ply == Sdepth + 1))) +#endif + depth = 1; + else if (score <= beta && + ((ply < Sdepth + 4) && (ply > 4) && + ChkFlag[ply - 2] && ChkFlag[ply - 4] && + ChkFlag[ply - 2] != ChkFlag[ply - 4])) + depth = 1; +#ifdef notdef + else if ( score >= alpha && + TesujiFlag[ply - 1] ) + depth = 1; +#endif + } + /*******************************************************************************************/ + /* try the local transition table if it's there */ + +#if ttblsz + if ( /* depth > 0 && */ flag.hash && ply > 1 ) + { + if (use_ttable && ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true) + { + bstline[ply] = PV; + bstline[ply + 1] = 0; +#ifdef DEBUG4 + if (debuglevel & 64) + { + algbr (PV >> 8, PV & 0xff, 0); + printf ("-get-> d=%d s=%d p=%d a=%d b=%d %s\n", depth, score, ply, alpha, beta, mvstr[0]); + } +#endif + if (beta == -((SCORE_LIMIT+1000)*2)) { + return (score); + } + if (alpha > beta) { + return (alpha); + } + } +#ifdef HASHFILE + /* ok try the transition file if its there */ + else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit) + && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true)) + { + PutInTTable (side, score, depth, ply, alpha, beta, PV); + bstline[ply] = PV; + bstline[ply + 1] = 0; + if (beta == -((SCORE_LIMIT+1000)*2)) { + return (score); + } + if (alpha > beta) { + return (alpha); + } +#ifdef DEBUG10 + else + { + FILE *D; + int r, c, l; + struct leaf far *xnode; + short side; + + D = fopen ("/tmp/DEBUG", "w"); + pnt = TrPnt[2]; + fprintf (D, "hashfile failure\n"); + algbr (PV >> 8, PV & 0xff, 0); + fprintf (D, "inout move is %s\n", mvstr); + fprintf (D, "legal move are \n"); + for (r = TrPnt[ply]; r < TrPnt[ply + 1]; r++) + { + xnode = &Tree[r]; + algbr (xnode->f, xnode->t, (short) xnode->flags); + fprintf (D, "%s %s %s %s\n", mvstr[0], mvstr[1], mvstr[2], mvstr[3]); + } + debug_position (D); + fclose (D); + } +#endif /* DEBUG10 */ + } +#endif /* HASHFILE */ + } +#endif /* ttblsz */ + + if ( TrPnt[ply] > TREE-300 ) + { + mustcut = true; +#ifdef NONDSP + printf("mustcut ply %d TrPnt[ply] %d\n",ply,TrPnt[ply]); +#endif + } + else + { + mustcut = false; + } + + /* + * if more then DepthBeyond ply past goal depth or at goal depth and + * score > beta quit - means we are out of the window + */ + if (mustcut || ply > DepthBeyond || (depth < 1 && score > beta)) + { + return (score); + } + + /* + * if below first ply and not at goal depth generate all moves else + * only capture moves + */ + if (ply > 1) + if (depth > 0 || ply < (SDEPTHLIM) || + (background && ply < Sdepth + 2)) + { + MoveList (side, ply, in_check, blockable); + } + else + { + CaptureList (side, ply, in_check, blockable); + } + + /* no moves return what we have */ + + /* + * normally a search will continue til past goal and no more capture + * moves exist + */ + /* unless it hits DepthBeyond */ + if (TrPnt[ply] == TrPnt[ply + 1]) + { + return (score); + } + + /* if not at goal set best = -inf else current score */ + best = (depth > 0) ? -(SCORE_LIMIT+3000) : score; +#ifdef NULLMOVE + + PVarisave = PVari; + if (!null && /* no previous null-move */ + !PVari && /* no null-move during the PV */ + (ply > 2) & /* not at ply 1 */ + (ply <= Sdepth) && + (depth > 3) && + !in_check) /* no check */ + /* enough material such that zugzwang is unlike but who knows which value + is suitable? */ + { + + /* ok, we make a null move, i.e. this means we have nothing to do + but we have to keep the some arrays up to date otherwise gnuchess + gets confused. Maybe somebody knows exactly which informations are + important and which not. + + Another idea is that we try the null-move first and generate the + moves later. This may save time but we have to take care that + PV and other variables contain the right value so that the move + ordering works right. + */ + register struct GameRec far *g; + + nxtline[ply + 1] = 0; + CptrFlag[ply] = 0; + TesujiFlag[ply] = 0; + Tscore[ply] = score; + PVsave = PV; + PV = 0; + null = 1; + g = &GameList[++GameCnt]; + g->hashkey = hashkey; + g->hashbd = hashbd; + FROMsquare = TOsquare = -1; + g->Game50 = Game50; + g->gmove = -1; + g->flags = 0; + g->piece = 0; + g->color = neutral; + + best = -search (xside, ply+1, depth - 2, - beta-1, -beta, nxtline, &rcnt); + null = 0; + PV = PVsave; + GameCnt--; + if (best < alpha) + best = -(SCORE_LIMIT+3000); + else if (best > beta) { + return (best); + } else + best = -(SCORE_LIMIT+3000); + } +#endif + /* if best so far is better than alpha set alpha to best */ + if (best > alpha) + alpha = best; + /********************** main loop ************************************************************************/ + /* look at each move until no more or beta cutoff */ + for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++) + { + /* find the most interesting looking of the remaining moves */ + if (ply > 1) + pick (pnt, TrPnt[ply + 1] - 1); +#ifdef NULLMOVE + PVari = PVarisave && (pnt == TrPnt[ply]); /* Is this the PV? */ +#endif + + node = &Tree[pnt]; + /* is this a forbidden move */ + if (/* ply == 1 && */ node->score <= DONTUSE) + continue; +#ifdef DEBUG + if(debuglevel & (512 | 1024)){ + if ( !tracen ) traceflag = ((ply >traceply)?false:true); + else + if(ply <= tracen && (ply ==1 || traceflag)) + { + if(trace[ply] == (Tree[pnt].t |(Tree[pnt].f<<8))) traceflag = true; else traceflag = false; } + tracelog[ply] = (Tree[pnt].t | (Tree[pnt].f<<8)); + tracelog[ply+1] = 0; +} +#endif + nxtline[ply + 1] = 0; + + /* if at top level */ +#if !defined NOPOST + if (ply == 1) + { /* at the top update search status */ + if (flag.post) +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + ShowCurrentMove (pnt, node->f, node->t); + } +#endif + if ( !(node->flags & exact) ) + { + /* make the move and go deeper */ +#ifdef DEBUG_EVAL + if ( debug_eval ) + { + algbr(node->f, node->t, 0); + fprintf(debug_eval_file,"%s (ply %d depth %d)\n", + mvstr[0], ply, depth); + } +#endif + MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore); + CptrFlag[ply] = (node->flags & capture); + TesujiFlag[ply] = (node->flags & tesuji) && (node->flags & dropmask); + Tscore[ply] = node->score; + PV = node->reply; +#ifdef DEBUG + xxxtmp = node->score; + tracetmp = traceflag; +#endif + node->score = -search (xside, ply + 1, + (depth > 0)?depth-1:0, + -beta, -alpha, + nxtline, &rcnt); +/* + if(!flag.timeout)node->score = score; +*/ + node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0; + if (node->score > SCORE_LIMIT || node->score < -SCORE_LIMIT) + node->flags |= exact; + else if (rcnt == 1) + node->score /= 2; +#ifdef DEBUG + traceflag = tracetmp; + if (debuglevel & 256 || ((debuglevel & 1024) && traceflag && + (!traceply || ply<= traceply))) { + int i; + algbr(node->f, node->t, node->flags); + for (i = 1; i < ply; i++) + printf(" "); + printf("%s S%d d%d p%d n%d s%d a%d b%d best%d x%d\n", + mvstr[0], Sdepth, depth, ply, node->score, score, alpha, beta, best,xxxtmp); + } +#endif + if ((rcnt >= 3 || (node->score == (SCORE_LIMIT+999) - ply && !ChkFlag[ply]))) + { + node->flags |= (draw | exact); + DRAW = CP[58]; /* Draw */ + node->score = ((side == computer) ? contempt : -contempt); + } + node->reply = nxtline[ply + 1]; + /* reset to try next move */ + UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst); + } + /* if best move so far */ + if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth)))) + { + /* + * all things being equal pick the denser part of the + * tree + */ + bestwidth = node->width; + + /* + * if not at goal depth and better than alpha and not + * an exact score increment by depth + */ + if (depth > 0 && node->score > alpha && !(node->flags & exact)) + { + node->score += depth; + } + best = node->score; + pbst = pnt; + if (best > alpha) { alpha = best; } + /* update best line */ + for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j]; + bstline[j] = 0; + bstline[ply] = (node->f << 8) | node->t; + /* if at the top */ + if (ply == 1) + { + /* + * if its better than the root score make it + * the root + */ + if ((best > root->score) || ((best == root->score) && (bestwidth > root->width))) + { + tmp = Tree[pnt]; + for (j = pnt - 1; j >= 0; j--) Tree[j + 1] = Tree[j]; + Tree[0] = tmp; + pbst = 0; + } +#ifndef BAREBONES +#ifdef QUIETBACKGROUND + if (!background) +#endif /* QUIETBACKGROUND */ + if (Sdepth > 2) + if (best > beta) + { + ShowResults (best, bstline, '+'); +#ifdef DEBUG41 + debug41 (best, bstline, '+'); +#endif + } + else if (best < alpha) + { + ShowResults (best, bstline, '-'); +#ifdef DEBUG41 + debug41 (best, bstline, '-'); +#endif + } + else + ShowResults (best, bstline, '&'); +#ifdef DEBUG41 + debug41 (best, bstline, '&'); +#endif +#else /* !BAREBONES */ + if ( !background && Sdepth > 2) { + if ( best < alpha) { + TCcount = 0; ExtraTime += 9*TCleft; + } + } +#endif + } + } + if (flag.timeout) + { + return (Tscore[ply - 1]); + } + } + + /******************************************************************************************/ + node = &Tree[pbst]; + mv = (node->f << 8) | node->t; +#ifdef NULLMOVE + PVari = PVarisave; +#endif +#ifdef DEBUG +if (debuglevel & 2560) +{ + int j; + + if (debuglevel & 512 && (tracen > 0 && traceflag)) + { + traceline[0]='\0'; + for (j=1;tracelog[j];j++){ + algbr(tracelog[j]>>8,tracelog[j]&0xff,0); + strcat(traceline," "); + strcat(traceline,mvstr[0]); + } + + printf("Ply %d alpha %d beta %d score %d %s\n", ply, alpha, beta, score,traceline); + if(debuglevel & 2048){ + for (j = ply; j < ply + 1; j++) + { + int idb; + + for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++) + { + algbr(Tree[idb].f, Tree[idb].t, Tree[idb].flags); + printf("level 512 %d-->%d %s %d %d %x\n", ply, idb, mvstr[0], Tree[idb].score, Tree[idb].width, Tree[idb].flags); + } + } +} +} + } + +#endif + + /* + * we have a move so put it in local table - if it's already there + * done else if not there or needs to be updated also put it in + * hashfile + */ +#if ttblsz + if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha) + { +#ifdef notdef +algbr(node->f,node->t,0); +printf("IN-> %lx %lx %d %d %s\n",hashkey,hashbd,depth,side,mvstr[0]); +#endif + if (use_ttable && PutInTTable (side, best, depth, ply, alpha, beta, mv) +#ifdef HASHFILE + && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)) + { +#ifdef notdef +printf("FT %d %d %d %x\n",side,best,depth,mv); +#endif + PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t); + } +#else + ); +#endif /* HASHFILE */ + } +#endif /* ttblsz */ + if (depth > 0) + { +#if defined HISTORY + unsigned short h,x; + h = mv; + if (history[x=hindex(side,h)] < HISTORYLIM) + history[x] += (unsigned short) 1<t != (short)(GameList[GameCnt].gmove & 0xFF)) + if (best <= beta) + killr3[ply] = mv; + else if (mv != killr1[ply]) + { + killr2[ply] = killr1[ply]; + killr1[ply] = mv; + } + killr0[ply] = ((best > SCORE_LIMIT) ? mv : 0); + } + return (best); +} + + +void +UpdatePieceList (short int side, short int sq, UpdatePieceList_mode iop) + +/* + * Update the PieceList and Pindex arrays when a piece is captured or when a + * capture is unmade. + */ + +{ + register short i; + + if (iop == REMOVE_PIECE) + { + PieceCnt[side]--; + for (i = Pindex[sq]; i <= PieceCnt[side]; i++) + { + PieceList[side][i] = PieceList[side][i + 1]; + Pindex[PieceList[side][i]] = i; + } + } + else + if ( board[sq] == king ) + { /* king must have index 0 */ + for (i = PieceCnt[side]; i >= 0; i--) + { + PieceList[side][i + 1] = PieceList[side][i]; + Pindex[PieceList[side][i + 1]] = i + 1; + } + PieceCnt[side]++; + PieceList[side][0] = sq; + Pindex[sq] = 0; + } + else + { + PieceCnt[side]++; + PieceList[side][PieceCnt[side]] = sq; + Pindex[sq] = PieceCnt[side]; + } +} + + +void +drop (short int side, short int piece, short int f, short int t, short int iop) + +/* Make or Unmake drop move. */ + +{ + if ( iop == 1 ) + { short cv, n; + board[t] = piece; + color[t] = side; +#if !defined SAVE_SVALUE + svalue[t] = 0; +#endif + n = Captured[side][piece]--; +#ifdef DEBUG + assert(n>0); +#endif + UpdateDropHashbd (side, piece, n); + UpdateHashbd (side, piece, -1, t); + UpdatePieceList (side, t, ADD_PIECE); + if ( piece == pawn ) + { + ++PawnCnt[side][column(t)]; + }; + Mvboard[t]++; + HasPiece[side][piece]++; + } + else + { short cv, n; + board[t] = no_piece; + color[t] = neutral; + n = ++Captured[side][piece]; +#ifdef DEBUG + assert(n>0); +#endif + UpdateDropHashbd (side, piece, n); + UpdateHashbd (side, piece, -1, t); + UpdatePieceList (side, t, REMOVE_PIECE); + if ( piece == pawn ) + { + --PawnCnt[side][column(t)]; + }; + Mvboard[t]--; + HasPiece[side][piece]--; + } + +} + + +#ifdef HASHKEYTEST +int +CheckHashKey () +{ unsigned long chashkey, chashbd; + short side, sq; + chashbd = chashkey = 0; + for (sq = 0; sq < NO_SQUARES; sq++) + { + if (color[sq] != neutral) + { + chashbd ^= (*hashcode)[color[sq]][board[sq]][sq].bd; + chashkey ^= (*hashcode)[color[sq]][board[sq]][sq].key; + } + /* hashcodes for initial board are 0 ! */ + if ( Stcolor[sq] != neutral ) + { + chashbd ^= (*hashcode)[Stcolor[sq]][Stboard[sq]][sq].bd; + chashkey ^= (*hashcode)[Stcolor[sq]][Stboard[sq]][sq].key; + } + } + for ( side = 0; side <= 1; side++ ) { + short piece; + for ( piece = 0; piece < NO_PIECES; piece++ ) { + short n = Captured[side][piece]; +#ifdef DEBUG + assert(n==0 || piece>0); +#endif + if ( n > 0 ) { + short i; + for ( i = 1; i <= n; i++ ) + { + chashbd ^= (*drop_hashcode)[side][piece][i].bd; + chashkey ^= (*drop_hashcode)[side][piece][i].key; + } + }; + }; + }; + if ( chashbd != hashbd ) + printf("chashbd %lu != hashbd %lu\n",chashbd,hashbd); + if ( chashkey != hashkey ) + printf("chashkey %lu != hashkey %lu\n",chashkey,hashkey); + if ( chashbd != hashbd || chashkey != hashkey ) { + return(1); + } + return(0); +}; +#endif + +void +MakeMove (short int side, + struct leaf far *node, + short int *tempb, /* piece at to square */ + short int *tempc, /* color of to square */ + short int *tempsf, /* static value of piece on from */ + short int *tempst, /* static value of piece on to */ + short int *INCscore) /* score increment */ + +/* + * Update Arrays board[], color[], and Pindex[] to reflect the new board + * position obtained after making the move pointed to by node. Also update + * miscellaneous stuff that changes when a move is made. + */ + +{ + register short f, t, xside, ct, cf; + register struct GameRec far *g; + register short int fromb,fromc; + + xside = side ^ 1; + g = &GameList[++GameCnt]; + g->hashkey = hashkey; + g->hashbd = hashbd; + FROMsquare = f = node->f; + TOsquare = t = (node->t & 0x7f); + *INCscore = (short int)node->INCscore; + g->Game50 = Game50; + g->gmove = (f << 8) | node->t; + g->flags = node->flags; + +#ifdef HASHKEYTEST + if ( CheckHashKey () ) { + short i; + algbr(f,t,node->flags); + printf("error before MakeMove: %s\n", mvstr[0]); + UpdateDisplay (0, 0, 1, 0); + for ( i=1; i<=GameCnt; i++ ) { + movealgbr(GameList[i].gmove,mvstr[0]); + printf("%d: %s\n", i, mvstr[0]); + } + exit(1); + } +#endif + + rpthash[side][hashkey & 0xFF]++, ISZERO++; + +#ifdef DEBUG + assert(f != NO_SQUARES); +#endif + + if (f > NO_SQUARES ) + { +#ifdef DEBUG + short piece; + piece = f - NO_SQUARES; + if ( side == white ) piece -= NO_PIECES; + assert(node->flags & dropmask); + assert((node->flags & pmask) == piece); +#endif + g->fpiece = (node->flags & pmask); + g->piece = *tempb = no_piece; + g->color = *tempc = neutral; +#if !defined SAVE_SVALUE + *tempsf = 0; + *tempst = svalue[t]; +#endif + (void) drop (side, g->fpiece, f, t, 1); + } + else + { short piece; + +#if !defined SAVE_SVALUE + *tempsf = svalue[f]; + *tempst = svalue[t]; +#endif + g->fpiece = board[f]; + g->piece = *tempb = board[t]; + g->color = *tempc = color[t]; + fromb = board[f]; + fromc = color[f]; + if (*tempc != neutral) + { /* Capture a piece */ + UpdatePieceList (*tempc, t, REMOVE_PIECE); + /* if capture decrement pawn count */ + if (*tempb == pawn) + { + --PawnCnt[*tempc][column (t)]; + } + mtl[xside] -= (*value)[stage][*tempb]; + HasPiece[xside][*tempb]--; + { short n, upiece = unpromoted[*tempb]; + /* add "upiece" captured by "side" */ + n = ++Captured[side][upiece]; +#ifdef DEBUG + assert(n>0); +#endif + UpdateDropHashbd (side, upiece, n); + mtl[side] += (*value)[stage][upiece]; + } + /* remove "*tempb" of "xside" from board[t] */ + UpdateHashbd (xside, *tempb, -1, t); +#if !defined SAVE_SVALUE + *INCscore += *tempst; /* add value of catched piece to own score */ +#endif + Mvboard[t]++; + } + color[t] = fromc; +#if !defined SAVE_SVALUE + svalue[t] = svalue[f]; + svalue[f] = 0; +#endif + Pindex[t] = Pindex[f]; + PieceList[side][Pindex[t]] = t; + color[f] = neutral; + board[f] = no_piece; + if (node->flags & promote) + { short tob; + board[t] = tob = promoted[fromb]; + /* remove unpromoted piece from board[f] */ + UpdateHashbd (side, fromb, f, -1); + /* add promoted piece to board[t] */ + UpdateHashbd (side, tob, -1, t); + mtl[side] += value[stage][tob] - value[stage][fromb]; + if ( fromb == pawn ) + { --PawnCnt[side][column(f)]; + }; + HasPiece[side][fromb]--; + HasPiece[side][tob]++; +#if !defined SAVE_SVALUE + *INCscore -= *tempsf; +#endif + } + else + { + board[t] = fromb; + /* remove piece from board[f] and add it to board[t] */ + UpdateHashbd (side, fromb, f, t); + } + Mvboard[f]++; + } +#ifdef HASHKEYTEST + algbr(f,t,node->flags); + if ( CheckHashKey () ) { + printf("error in MakeMove: %s\n", mvstr[0]); + exit(1); + } +#endif +#ifdef DEBUG + assert(Captured[black][0]==0 && Captured[white][0]==0); +#endif +} + +void +UnmakeMove (short int side, + struct leaf far *node, + short int *tempb, + short int *tempc, + short int *tempsf, + short int *tempst) + +/* + * Take back a move. + */ + +{ + register short f, t, xside; + + xside = side ^ 1; + f = node->f; + t = node->t & 0x7f; + Game50 = GameList[GameCnt].Game50; + +#ifdef DEBUG + assert(f != NO_SQUARES); + + if (f > NO_SQUARES ) + { short piece; + piece = f - NO_SQUARES; + if ( piece >= NO_PIECES ) piece -= NO_PIECES; + assert(node->flags & dropmask); + assert((node->flags & pmask) == piece); + } +#endif + + if (node->flags & dropmask) + { + (void) drop (side, (node->flags & pmask), f, t, 2); +#if !defined SAVE_SVALUE + svalue[t] = *tempst; +#endif + } + else + { short tob, fromb; + color[f] = color[t]; + board[f] = tob = fromb = board[t]; +#if !defined SAVE_SVALUE + svalue[f] = *tempsf; +#endif + Pindex[f] = Pindex[t]; + PieceList[side][Pindex[f]] = f; + color[t] = *tempc; + board[t] = *tempb; +#if !defined SAVE_SVALUE + svalue[t] = *tempst; +#endif + /* Undo move */ + if (node->flags & promote) + { + board[f] = fromb = unpromoted[tob]; + mtl[side] += value[stage][fromb] - value[stage][tob]; + if ( fromb == pawn ) + { + ++PawnCnt[side][column (f)]; + } + HasPiece[side][fromb]++; + HasPiece[side][tob]--; + /* add unpromoted piece to board[f] */ + UpdateHashbd (side, fromb, f, -1); + /* remove promoted piece from board[t] */ + UpdateHashbd (side, tob, -1, t); + } + else + { + if ( fromb == pawn ) + { + --PawnCnt[side][column (t)]; + ++PawnCnt[side][column (f)]; + }; + /* remove piece from board[t] and add it to board[f] */ + UpdateHashbd (side, fromb, f, t); + } + /* Undo capture */ + if (*tempc != neutral) + { short n, upiece = unpromoted[*tempb]; + UpdatePieceList (*tempc, t, ADD_PIECE); + if (*tempb == pawn) + { + ++PawnCnt[*tempc][column (t)]; + } + mtl[xside] += (*value)[stage][*tempb]; + HasPiece[xside][*tempb]++; + mtl[side] -= (*value)[stage][upiece]; + /* remove "upiece" captured by "side" */ + n = Captured[side][upiece]--; +#ifdef DEBUG + assert(n>0); +#endif + UpdateDropHashbd (side, upiece, n); + /* replace captured piece on board[t] */ + UpdateHashbd (xside, *tempb, -1, t); + Mvboard[t]--; + } + Mvboard[f]--; + } + GameCnt--; + rpthash[side][hashkey & 0xFF]--, ISZERO--; +#ifdef HASHKEYTEST + algbr(f,t,node->flags); + if ( CheckHashKey () ) { + printf("error in UnmakeMove: %s\n", mvstr[0]); + exit(1); + } +#endif +#ifdef DEBUG + assert(Captured[black][0]==0 && Captured[white][0]==0); +#endif +} + + +void +InitializeStats (void) + +/* + * Scan thru the board seeing what's on each square. If a piece is found, + * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also + * determine the material for each side and set the hashkey and hashbd + * variables to represent the current board position. Array + * PieceList[side][indx] contains the location of all the pieces of either + * side. Array Pindex[sq] contains the indx into PieceList for a given + * square. + */ + +{ + register short i, sq; + + for (i = 0; i < NO_COLS; i++) + { + PawnCnt[black][i] = PawnCnt[white][i] = 0; + } + mtl[black] = mtl[white] = 0; + PieceCnt[black] = PieceCnt[white] = 0; + hashbd = hashkey = 0; + for (sq = 0; sq < NO_SQUARES; sq++) + { + if (color[sq] != neutral) + { + mtl[color[sq]] += (*value)[stage][board[sq]]; + if (board[sq] == pawn) + { + ++PawnCnt[color[sq]][column(sq)]; + } + Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]); + + PieceList[color[sq]][Pindex[sq]] = sq; + UpdateHashbd(color[sq],board[sq],sq,-1); + } + /* hashcodes for initial board are 0 ! */ + if ( Stcolor[sq] != neutral ) + UpdateHashbd(Stcolor[sq],Stboard[sq],sq,-1); + } + { short side; + for ( side = 0; side <= 1; side++ ) { + short piece; + for ( piece = 0; piece < NO_PIECES; piece++ ) { + short n = Captured[side][piece]; + if ( n > 0 ) { + Captured[side][piece] = 0; + for ( i = 1; i <= n; i++ ) { + ++Captured[side][piece]; + UpdateDropHashbd(side,piece,i); + mtl[side] += (*value)[stage][piece]; + }; + }; + }; + }; + } +#ifdef HASHKEYTEST + if ( CheckHashKey () ) { + printf("error in InitializeStats\n"); + exit(1); + } +#endif + +} diff --git a/src/sizetest.c b/src/sizetest.c new file mode 100644 index 0000000..9cc0f87 --- /dev/null +++ b/src/sizetest.c @@ -0,0 +1,293 @@ +/* + * sizetest.c - display memory usage of GNU SHOGI data + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz (GNU Shogi) + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "version.h" +#include "gnushogi.h" + +#include + +#if defined THINK_C +#include +#include +#endif + +struct leaf far *Tree, *root; + +short FROMsquare, TOsquare; + +small_short ChkFlag[MAXDEPTH], CptrFlag[MAXDEPTH], TesujiFlag[MAXDEPTH]; +short Pscore[MAXDEPTH], Tscore[MAXDEPTH]; +small_short Pindex[NO_SQUARES]; + +short mtl[2], hung[2]; +small_short PieceCnt[2]; + +struct GameRec far *GameList; + +char ColorStr[2][10]; + +long znodes; + + +#if defined HASGETTIMEOFDAY && defined THINK_C + +#define USEC_PER_CLOCK (1000000 / CLOCKS_PER_SEC) + +int gettimeofday(struct timeval *tp, void *tzp) +{ + long clock_count = (long)clock(); + tp->tv_sec = clock_count / CLOCKS_PER_SEC; + tp->tv_usec = (clock_count % CLOCKS_PER_SEC) * USEC_PER_CLOCK; + return(0); +} + +#endif + +/* + * In a networked enviroment gnuchess might be compiled on different hosts + * with different random number generators, that is not acceptable if they + * are going to share the same transposition table. + */ +unsigned long int next = 1; + +unsigned int +urand (void) +{ + next *= 1103515245; + next += 12345; + return ((unsigned int) (next >> 16) & 0xFFFF); +} + +void +gsrand (unsigned int seed) +{ + next = seed; +} + +#if ttblsz +struct hashentry *ttable[2]; +unsigned int ttblsize; +#endif +#ifdef BINBOOK +extern char *binbookfile; +#endif +extern char *bookfile; + +char savefile[128] = ""; +char listfile[128] = ""; + +#if defined HISTORY +unsigned short far *history; +#endif + +short rpthash[2][256]; +short TrPnt[MAXDEPTH]; +small_short PieceList[2][NO_SQUARES]; +small_short PawnCnt[2][NO_COLS]; +small_short Captured[2][NO_PIECES]; +small_short Mvboard[NO_SQUARES]; +#if !defined SAVE_SVALUE +short svalue[NO_SQUARES]; +#endif +struct flags flag; + +short opponent, computer, WAwindow, WBwindow, BAwindow, BBwindow, dither, + INCscore; +long ResponseTime, ExtraTime, MaxResponseTime, et, et0, time0, ft; +long GenCnt, NodeCnt, ETnodes, EvalNodes, HashCnt, HashAdd, FHashCnt, FHashAdd, + HashCol, THashCol, filesz, hashmask, hashbase; +long replus, reminus; +short HashDepth = HASHDEPTH, HashMoveLimit = HASHMOVELIMIT; +short player, xwndw; +/*unsigned*/ short rehash; /* -1 is used as a flag --tpm */ +short Sdepth, Game50, MaxSearchDepth; +short GameCnt = 0; +short contempt; +int Book; +struct TimeControlRec TimeControl; +int TCadd = 0; +short TCflag, TCmoves, TCminutes, TCseconds, OperatorTime; +short XCmoves[3], XCminutes[3], XCseconds[3], XC, XCmore; +const short otherside[3] = +{white, black, neutral}; +unsigned short hint; +short int TOflag; /* force search re-init if we backup search */ + +unsigned short killr0[MAXDEPTH], killr1[MAXDEPTH]; +unsigned short killr2[MAXDEPTH], killr3[MAXDEPTH]; +unsigned short PV, SwagHt, Swag0, Swag1, Swag2, Swag3, Swag4, sidebit; + +small_short HasPiece[2][NO_PIECES]; +const short kingP[3] = +{4, 76, 0}; + +const long control[NO_PIECES] = +{0, ctlP, ctlL, ctlN, ctlS, ctlG, ctlB, ctlR, + ctlPp, ctlLp, ctlNp, ctlSp, ctlBp, ctlRp, ctlK }; + +short stage, stage2; + +FILE *hashfile; + +unsigned int starttime; +short int ahead = true, hash = true; + + + +#if defined XSHOGI +void +TerminateChess (int sig) +{ + ExitChess (); +} + +#endif + + + +int timeopp[MINGAMEIN], timecomp[MINGAMEIN]; +int compptr, oppptr; + +void +TimeCalc () +{ +/* adjust number of moves remaining in gamein games */ + int increment = 0; + int topsum = 0; + int tcompsum = 0; + int me,him; + int i; +/* dont do anything til you have enough numbers */ + if (GameCnt < (MINGAMEIN * 2)) return; +/* calculate average time in sec for last MINGAMEIN moves */ + for (i = 0; i < MINGAMEIN; i++) + { + tcompsum += timecomp[i]; + topsum += timeopp[i]; + } + topsum /= (100 * MINGAMEIN); + tcompsum /= (100 * MINGAMEIN); +/* if I have less time than opponent add another move */ + me = TimeControl.clock[computer]/100; + him = TimeControl.clock[opponent]/100; + if(me < him) increment += 2; + if((him - me) > 60 || (me 60) && tcompsum > topsum) increment++;*/ + if ( tcompsum > topsum) increment +=2; +/* but dont let moves go below MINMOVES */ + else if (TimeControl.moves[computer] < MINMOVES && !increment) increment++; +/* if I am doing really well use more time per move */ + else if (me > him && tcompsum < topsum) increment = -1; + TimeControl.moves[computer] += increment; +} + + + + + +int +main (int argc, char **argv) +{ + long l; + int n; + +#ifdef THINK_C + console_options.ncols = 100; + cshow(stdout); +#endif + +#if ttblsz + l = (long)sizeof(struct hashentry); + n = (int)((l * (ttblsz + rehash) * 2) / 1000); + printf("ttable:\t\t%4d\tkByte\t[hashentry:%ld * (ttblsz:%d + rehash:%d) * 2]\n", + n,l,ttblsz,rehash); +#endif + +#if defined CACHE + l = (long)sizeof(struct etable); + n = (int)((l * (size_t)ETABLE) / 1000); +#else + l = n = 0; +#endif + printf("etab:\t\t%4d\tkByte\t[etable:%ld ETABLE:%d]\n",n,l,ETABLE); + + l = (long)sizeof(struct leaf); + n = (int)(l * TREE / 1000); + printf("Tree:\t\t%4d\tkByte\t[leaf:%ld * TREE:%d]\n",n,l,TREE); + +#if defined HISTORY + n = (int)(sizeof_history / 1000); +#else + n = 0; +#endif + printf("history:\t%4d\tkByte\t[unsigned short:%ld * HISTORY_SIZE:%ld]\n", + n,sizeof(unsigned short),(long)HISTORY_SIZE); + +#ifdef SAVE_NEXTPOS +#else + l = (long)sizeof(next_array); + n = (int)((l * NO_PTYPE_PIECES) / 1000); + printf("nextpos:\t%4d\tkByte\t[next_array:%ld * NO_PTYPE_PIECES:%d]\n", + n,l,NO_PTYPE_PIECES); + + l = (long)sizeof(next_array); + n = (int)((l * NO_PTYPE_PIECES) / 1000); + printf("nextdir:\t%4d\tkByte\t[next_array:%ld * NO_PTYPE_PIECES:%d]\n", + n,l,NO_PTYPE_PIECES); +#endif + +#ifdef SAVE_DISTDATA +#else + n = (int)(sizeof(distdata_array) / 1000); + printf("distdata:\t%4d\tkByte\n",n); +#endif + +#ifdef SAVE_PTYPE_DISTDATA +#else + l = (long)sizeof(distdata_array); + n = (int)((l * NO_PTYPE_PIECES) / 1000); + printf("ptype_distdata:\t%4d\tkByte\t[distdata_array:%ld * NO_PTYPE_PIECES:%d]\n", + n,l,NO_PTYPE_PIECES); +#endif + + l = (long)sizeof(hashcode_array); + n = (int)(l / 1000); + printf("hashcode:\t%4d\tkByte\t[hashval:%ld]\n", + n,(long)sizeof(struct hashval)); + + l = (long)sizeof(drop_hashcode_array); + n = (int)(l / 1000); + printf("drop_hashcode:\t%4d\tkByte\t[hashval:%ld]\n", + n,(long)sizeof(struct hashval)); + + l = (long)sizeof(value_array); + n = (int)(l / 1000); + printf("value:\t\t%4d\tkByte\n",n); + + l = (long)sizeof(fscore_array); + n = (int)(l / 1000); + printf("fscore:\t\t%4d\tkByte\n",n); + +} + diff --git a/src/tcontrl.c b/src/tcontrl.c new file mode 100644 index 0000000..7b4db94 --- /dev/null +++ b/src/tcontrl.c @@ -0,0 +1,302 @@ +/* + * tcontrl.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" + +#ifdef DEBUG +#include +#else +#include +#endif + +#define ALTERNATIVE_TC + +#if !defined OLDTIME && defined HASGETTIMEOFDAY +double pow(); +#endif + + +/* + * In a networked enviroment gnuchess might be compiled on different hosts + * with different random number generators, that is not acceptable if they + * are going to share the same transposition table. + */ + +static unsigned long int next = 1; + +unsigned int +urand (void) +{ + next *= 1103515245; + next += 12345; + return ((unsigned int) (next >> 16) & 0xFFFF); +} + +void +gsrand (unsigned int seed) +{ + next = seed; +} + + + +void +TimeCalc () +{ +/* adjust number of moves remaining in gamein games */ + int increment = 0; + int topsum = 0; + int tcompsum = 0; + int me,him; + int i; +/* dont do anything til you have enough numbers */ + if (GameCnt < (MINGAMEIN * 2)) return; +/* calculate average time in sec for last MINGAMEIN moves */ + for (i = 0; i < MINGAMEIN; i++) + { + tcompsum += timecomp[i]; + topsum += timeopp[i]; + } + topsum /= (100 * MINGAMEIN); + tcompsum /= (100 * MINGAMEIN); +/* if I have less time than opponent add another move */ + me = TimeControl.clock[computer]/100; + him = TimeControl.clock[opponent]/100; + if(me < him) increment += 2; + if((him - me) > 60 || (me 60) && tcompsum > topsum) increment++;*/ + if ( tcompsum > topsum) increment +=2; +/* but dont let moves go below MINMOVES */ + else if (TimeControl.moves[computer] < MINMOVES && !increment) increment++; +/* if I am doing really well use more time per move */ + else if (me > him && tcompsum < topsum) increment = -1; +/* if not fischer clock be careful about time */ + if(TCadd == 0 && increment >0)increment += 2; + if(me == 0 && increment >0)increment += 2; + TimeControl.moves[computer] += increment; +} + + + + +/* + * Set ResponseTime, TCcount, and TCleft. + */ + +void SetResponseTime (short int side) +{ + +#ifdef ALTERNATIVE_TC + + int DetermineTCcount = true; + + if (TCflag) + { + TCcount = 0; + if (TimeControl.moves[side] < 1) + TimeControl.moves[side] = 1; + /* special case time per move specified */ + if (flag.onemove) + { + ResponseTime = TimeControl.clock[side] - 100; + TCleft = 0; + } + else + { + /* calculate avg time per move remaining */ + if ( TimeControl.clock[side] <= 0 ) + { + ResponseTime = 0; + TCleft = (long)MINRESPONSETIME / MAXTCCOUNTX; + } + else + { +#ifdef DEBUG + char buffer[80]; +#endif + short rtf = in_opening_stage ? 8 : 2; + short tcq = in_opening_stage ? 2 : 4; + TimeControl.clock[side] += TCadd; + ResponseTime = + (TimeControl.clock[side]) / + (((TimeControl.moves[side]) * rtf) + 1); + TCleft = (long)ResponseTime / tcq; + ResponseTime += TCadd/2; +#ifdef DEBUG + sprintf(buffer,"rtf=%d tcq=%d rt=%ld tl=%ld", + rtf,tcq,ResponseTime,TCleft); + ShowMessage(buffer); +#endif + } + if (TimeControl.moves[side] < 5) + { + TCcount = MAXTCCOUNTX - 10; + if ( TCcount < 0 ) TCcount = 0; + DetermineTCcount = false; + } + } + if (ResponseTime < MINRESPONSETIME) + { + ResponseTime = MINRESPONSETIME; + TCcount = MAXTCCOUNTX - 10; + if ( TCcount < 0 ) TCcount = 0; + DetermineTCcount = false; + } +#ifndef HARDTIMELIMIT + else if (ResponseTime < 2*MINRESPONSETIME) + { + TCcount = MAXTCCOUNTX - 10; + if ( TCcount < 0 ) TCcount = 0; + DetermineTCcount = false; + } +#endif + } + else + { + TCleft = 0; + ResponseTime = MaxResponseTime; + ElapsedTime(COMPUTE_AND_INIT_MODE); + } + + if ( DetermineTCcount ) + if ( TCleft ) + { + int AllowedCounts = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft; + + if ( AllowedCounts <= 0 ) + TCcount = MAXTCCOUNTX; + else if (AllowedCounts > MAXTCCOUNTX) + TCcount = 0; + else + TCcount = MAXTCCOUNTX - AllowedCounts; + } + else + { + TCcount = MAXTCCOUNTX; + } + + if ( ResponseTime < MINRESPONSETIME ) + ResponseTime = MINRESPONSETIME; + +#else + + if (TCflag) + { + TCcount = 0; + if (TimeControl.moves[side] < 1) + TimeControl.moves[side] = 1; + /* special case time per move specified */ + if (flag.onemove) + { + ResponseTime = TimeControl.clock[side] - 100; + TCleft = 0; + } + else + { + /* calculate avg time per move remaining */ + TimeControl.clock[side] += TCadd; + + ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1); + TCleft = (int) ResponseTime / 3; + ResponseTime += TCadd / 2; + if (TimeControl.moves[side] < 5) + TCcount = MAXTCCOUNTX - 10; + } + if (ResponseTime < 101) + { + ResponseTime = 100; + TCcount = MAXTCCOUNTX - 10; + } + else if (ResponseTime < 200) + { + TCcount = MAXTCCOUNTX - 10; + } + } + else + { + ResponseTime = MaxResponseTime; + TCleft = 0; + ElapsedTime (COMPUTE_AND_INIT_MODE); + } + if (TCleft) + { + TCcount = ((int) ((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft; + if (TCcount > MAXTCCOUNTX) + TCcount = 0; + else + TCcount = MAXTCCOUNTX - TCcount; + } + else + TCcount = MAXTCCOUNTX; + +#endif + + assert(TCcount <= MAXTCCOUNTX); + +} + + +void CheckForTimeout (int score, int globalscore, int Jscore, int zwndw) +{ + if (flag.musttimeout || Sdepth >= MaxSearchDepth) + flag.timeout = true; + + else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR)) + { + if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ ) + { + TCcount++; + ExtraTime += TCleft; + } + if (TCcount < MAXTCCOUNTR && (abs (score - globalscore) / Sdepth) > ZDELTA) + { + TCcount++; + ExtraTime += TCleft; + } + } + if (score > (Jscore - zwndw) && score > (Tree[1].score + 250)) + ExtraTime = 0; + ElapsedTime(COMPUTE_MODE); + if (root->flags & exact) + flag.timeout = true; + /*else if (Tree[1].score < -SCORE_LIMIT) flag.timeout = true;*/ +#if defined OLDTIME || !defined HASGETTIMEOFDAY + else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime))) + flag.timeout = true; +#else + else if (!(Sdepth < MINDEPTH) && TCflag && + ((int)(1.93913099l * (pow((double)et,1.12446928l))) > (ResponseTime + ExtraTime))) + flag.timeout = true; +#endif +#if !defined BAREBONES + if ( flag.timeout ) + ShowMessage("timeout"); +#endif +} + + diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..98d9902 --- /dev/null +++ b/src/util.c @@ -0,0 +1,605 @@ +/* + * util.c - C source for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gnushogi.h" +#ifdef DEBUG +#include +#endif +unsigned int TTadd = 0; +short int recycle; +short int ISZERO = 1; + + +int +parse (FILE * fd, short unsigned int *mv, short int side, char *opening) +{ + register int c, i, r1, r2, c1, c2; + char s[128]; + char *p; + + while ((c = getc (fd)) == ' ' || c == '\n') ; + i = 0; + s[0] = (char) c; + if (c == '!') + { + p = opening; + do + { + *p++ = c; + c = getc (fd); + if (c == '\n' || c == EOF) + { + *p = '\0'; + return 0; + } + } while (true); + } + while (c != '?' && c != ' ' && c != '\t' && c != '\n' && c != EOF) + s[++i] = (char) (c = getc (fd)); + s[++i] = '\0'; + if (c == EOF) + return (-1); + if (s[0] == '!' || s[0] == ';' || i < 3) + { + while (c != '\n' && c != EOF) + c = getc (fd); + return (0); + } + c1 = '9' - s[0]; + r1 = 'i' - s[1]; + c2 = '9' - s[2]; + r2 = 'i' - s[3]; + *mv = (locn (r1, c1) << 8) | locn (r2, c2); + if (c == '?') + { /* Bad move, not for the program to play */ + *mv |= 0x8000; /* Flag it ! */ + c = getc (fd); + } + return (1); +} + + +/* + * The field of a hashtable is computed as follows: + * if sq is on board (< NO_SQUARES) the field gets the value + * of the piece on the square sq; + * if sq is off board (>= NO_SQUARES) it is a catched figure, + * and the field gets the number of catched pieces for + * each side. + */ + + +inline +unsigned char +CB (short sq) +{ + register short i = sq; + if ( i < NO_SQUARES ) { + return ( (color[i] == white) ? (0x80 | board[i]) : board[i] ); + } else { +#ifdef DEBUG + assert(i!=NO_SQUARES || (Captured[black][0]==0 && Captured[white][0]==0)); +#endif + i -= NO_SQUARES; + return ( (Captured[black][i] << 4) | Captured[white][i] ); + } +} + + + +#if defined DEBUG + +inline +char +BDpiece(unsigned char p) +{ + unsigned short piece = p & 0x7f; + if ( piece == no_piece ) + return '-'; + else if ( p & 0x80 ) + return qxx[piece]; + else + return pxx[piece]; +} + +inline +char +BDpromoted(unsigned char p) +{ + unsigned short piece = p & 0x7f; + if ( is_promoted[piece] ) + return '+'; + else + return ' '; +} + +void +ShowBD(unsigned char bd[]) +{ + register short i; + for ( i = 0; i < PTBLBDSIZE; i++) + { + if ( i < NO_SQUARES ) + { + printf("%c%c(%c%c) ", + BDpromoted(bd[i]),BDpiece(bd[i]), + BDpromoted(CB(i)),BDpiece(CB(i))); + if ( i % NO_COLS == NO_COLS - 1 ) + printf("\n"); + } + else + printf("%2x(%2x) ",bd[i],CB(i)); + }; + printf("\n"); +} + +#endif + + + +#if ttblsz + + + +#ifdef DEBUG_TTABLE + +void ShowPTBL (struct hashentry *ptbl) +{ + movealgbr(ptbl->mv,mvstr[0]); + printf("hk=%lx hb=%lx ptbl=%lx bd=%lx mv=%s d=%d f=%d s=%d\n", + hashkey, hashbd, ptbl, + ptbl->hashbd, mvstr[0], ptbl->depth, ptbl->flags, ptbl->score); +} +#endif + + +int +ProbeTTable (short int side, + short int depth, + short int ply, + short int *alpha, + short int *beta, + short int *score) + +/* + * Look for the current board position in the transposition table. + */ + +{ + register struct hashentry far *ptbl; + register /*unsigned*/ short i = 0; /*to match new type of rehash --tpm*/ + +#ifdef DEBUG_TTABLE + /* printf("FOR hk=%lx hb=%lx d=%d\n",hashkey,hashbd,depth); */ +#endif + + ptbl = &ttable[side][hashkey % ttblsize]; + + while (true) + { + if ((ptbl->depth) == 0) + return false; + if (ptbl->hashbd == hashbd) + break; + if (++i > rehash) + return false; + ptbl++; + } + + /* rehash max rehash times */ + if (((short)(ptbl->depth) >= (short) depth)) + { +#ifdef HASHTEST + for (i = 0; i < PTBLBDSIZE; i++) + { + if (ptbl->bd[i] != CB (i)) + { +#ifndef BAREBONES + HashCol++; + ShowMessage (CP[199]); /*ttable collision detected*/ + ShowBD(ptbl->bd); + printf("hashkey = 0x%x, hashbd = 0x%x\n", hashkey, hashbd); +#endif + break; + } + } +#endif /* HASHTEST */ + + + PV = SwagHt = ptbl->mv; +#if !defined BAREBONES + HashCnt++; +#endif + if (ptbl->flags & truescore) + { + *score = ptbl->score; + /* adjust *score so moves to mate is from root */ + if (*score > SCORE_LIMIT) + *score -= ply; + else if (*score < -SCORE_LIMIT) + *score += ply; + *beta = -2*(SCORE_LIMIT+1000); + } + else if (ptbl->flags & lowerbound) + { + if (ptbl->score > *alpha) + *alpha = ptbl->score - 1; + } +#ifdef DEBUG_TTABLE + /* printf("GET "); ShowPTBL(ptbl); */ +#endif + return (true); + } + return (false); +} + + +int +PutInTTable (short int side, + short int score, + short int depth, + short int ply, + short int alpha, + short int beta, + short unsigned int mv) + +/* + * Store the current board position in the transposition table. + */ + +{ + register struct hashentry far *ptbl; + register /*unsigned*/ short i = 0; /*to match new type of rehash --tpm*/ + + ptbl = &ttable[side][hashkey % ttblsize]; + + while (true) + { + if ((ptbl->depth) == 0 || ptbl->hashbd == hashbd) + break; + if (++i > rehash) + { +#ifndef BAREBONES + THashCol++; +#endif + ptbl += recycle; + break; + } + ptbl++; + } + +#ifndef BAREBONES + TTadd++; + HashAdd++; +#endif + /* adjust score so moves to mate is from this ply */ + if (score > SCORE_LIMIT) + score += ply; + else if (score < -SCORE_LIMIT) + score -= ply; + ptbl->hashbd = hashbd; + ptbl->depth = (unsigned char) depth; + ptbl->score = score; + ptbl->mv = mv; + +#ifdef DEBUG4 + if (debuglevel & 32) + { + algbr (mv >> 8, mv & 0xff, 0); + printf ("-add-> d=%d s=%d p=%d a=%d b=%d %s\n", depth, score, ply, alpha, beta, mvstr); + } +#endif + if (score > beta) + { + ptbl->flags = lowerbound; + ptbl->score = beta + 1; + } + else + ptbl->flags = truescore; + +#if defined HASHTEST + for (i = 0; i < PTBLBDSIZE; i++) + { + ptbl->bd[i] = CB (i); + } +#endif /* HASHTEST */ + +#ifdef DEBUG_TTABLE + /* printf("PUT "); ShowPTBL(ptbl); */ +#endif + + return true; +} + + +#if ttblsz +static struct hashentry far *ttageb, *ttagew; +#endif + +void +ZeroTTable (void) +{ +#ifdef notdef + register struct hashentry far *w, *b; + for ( b=ttable[black], w=ttable[white]; b < &ttable[black][ttblsize]; w++, b++) + { + w->depth = 0; + b->depth = 0; + } + ttageb = ttable[black]; + ttagew = ttable[white]; + register unsigned int a; + for (a = 0; a < ttblsize + (unsigned int)rehash; a++) + { + (ttable[black])[a].depth = 0; + (ttable[white])[a].depth = 0; + } +#endif + array_zero(ttable[black],(ttblsize+rehash)); + array_zero(ttable[white],(ttblsize+rehash)); +#ifdef DEBUG_TTABLE + printf("TTable zeroed\n"); +#endif +#ifdef CACHE + array_zero(etab[0],sizeof(struct etable)*(size_t)ETABLE); + array_zero(etab[1],sizeof(struct etable)*(size_t)ETABLE); +#endif + TTadd = 0; +} + +#ifdef HASHFILE +int Fbdcmp(unsigned char *a,unsigned char *b) +{ + register int i; + for(i = 0; i < PTBLBDSIZE; i++) + if(a[i] != b[i]) return false; + return true; +} +int +ProbeFTable (short int side, + short int depth, + short int ply, + short int *alpha, + short int *beta, + short int *score) + +/* + * Look for the current board position in the persistent transposition table. + */ + +{ + register short int i; + register unsigned long hashix; + struct fileentry new, t; + + hashix = ((side == black) ? (hashkey & 0xFFFFFFFE) : (hashkey | 1)) % filesz; + + for (i = 0; i < PTBLBDSIZE; i++) + new.bd[i] = CB (i); + new.flags = 0; + for (i = 0; i < frehash; i++) + { + fseek (hashfile, + sizeof (struct fileentry) * ((hashix + 2 * i) % (filesz)), + SEEK_SET); + fread (&t, sizeof (struct fileentry), 1, hashfile); + if (!t.depth) break; + if(!Fbdcmp(t.bd, new.bd)) continue; + if (((short int) t.depth >= depth) + && (new.flags == (unsigned short)(t.flags & (kingcastle | queencastle)))) + { +#if !defined BAREBONES + FHashCnt++; +#endif + PV = (t.f << 8) | t.t; + *score = (t.sh << 8) | t.sl; + /* adjust *score so moves to mate is from root */ + if (*score > SCORE_LIMIT) + *score -= ply; + else if (*score < -SCORE_LIMIT) + *score += ply; + if (t.flags & truescore) + { + *beta = -((SCORE_LIMIT+1000)*2); + } + else if (t.flags & lowerbound) + { + if (*score > *alpha) + *alpha = *score - 1; + } + else if (t.flags & upperbound) + { + if (*score < *beta) + *beta = *score + 1; + } + return (true); + } + } + return (false); +} + +void +PutInFTable (short int side, + short int score, + short int depth, + short int ply, + short int alpha, + short int beta, + short unsigned int f, + short unsigned int t) + +/* + * Store the current board position in the persistent transposition table. + */ + +{ + register unsigned short i; + register unsigned long hashix; + struct fileentry new, tmp; + + hashix = ((side == black) ? (hashkey & 0xFFFFFFFE) : (hashkey | 1)) % filesz; + for (i = 0; i < PTBLBDSIZE; i++) + new.bd[i] = CB (i); + new.f = (unsigned char) f; + new.t = (unsigned char) t; + if (score < alpha) + new.flags = upperbound; + else + new.flags = ((score > beta) ? lowerbound : truescore); + new.depth = (unsigned char) depth; + /* adjust *score so moves to mate is from root */ + if (score > SCORE_LIMIT) + score += ply; + else if (score < -SCORE_LIMIT) + score -= ply; + + + new.sh = (unsigned char) (score >> 8); + new.sl = (unsigned char) (score & 0xFF); + + for (i = 0; i < frehash; i++) + { + fseek (hashfile, + sizeof (struct fileentry) * ((hashix + 2 * i) % (filesz)), + SEEK_SET); + if ( !fread (&tmp, sizeof (struct fileentry), 1, hashfile) ) + {perror("hashfile");exit(1);} + if (tmp.depth && !Fbdcmp(tmp.bd,new.bd))continue; + if (tmp.depth == depth) break; + if (!tmp.depth || (short) tmp.depth < depth) + { + fseek (hashfile, + sizeof (struct fileentry) * ((hashix + 2 * i) % (filesz)), + SEEK_SET); +#ifdef DEBUG4 + if (debuglevel & 32) + { + printf ("-fadd\n"); + } +#endif + fwrite (&new, sizeof (struct fileentry), 1, hashfile); +#if !defined BAREBONES + FHashAdd++; +#endif + break; + } + } +} + +#endif /* HASHFILE */ +#endif /* ttblsz */ + +void +ZeroRPT (void) +{ + if ( ISZERO ) + { + array_zero (rpthash, sizeof (rpthash)); + ISZERO = 0; + } +} + + + + +#if defined CACHE + +void +PutInEETable (short int side,int score) + +/* + * Store the current eval position in the transposition table. + */ + +{ + register struct etable far *ptbl; + ptbl = &(*etab[side])[hashkey % (ETABLE)]; + ptbl->ehashbd = hashbd; + ptbl->escore[black] = pscore[black]; + ptbl->escore[white] = pscore[white]; + ptbl->hung[black] = hung[black]; + ptbl->hung[white] = hung[white]; + ptbl->score = score; +#if !defined SAVE_SSCORE + array_copy (svalue, &(ptbl->sscore), sizeof (svalue)); +#endif +#if !defined BAREBONES + EADD++; +#endif + return; +} + + +int +CheckEETable (short int side) + +/* Get an evaluation from the transposition table */ +{ + register struct etable far *ptbl; + ptbl = &(*etab[side])[hashkey % (ETABLE)]; + if (hashbd == ptbl->ehashbd) + { + return true; + } + return false; +} + + +int +ProbeEETable (short int side, short int *score) + +/* Get an evaluation from the transposition table */ +{ + register struct etable far *ptbl; + ptbl = &(*etab[side])[hashkey % (ETABLE)]; + if (hashbd == ptbl->ehashbd) + { + pscore[black] = ptbl->escore[black]; + pscore[white] = ptbl->escore[white]; +#if defined SAVE_SSCORE + array_zero (svalue, sizeof(svalue)); +#else + array_copy (&(ptbl->sscore), svalue, sizeof (svalue)); +#endif + *score = ptbl->score; + hung[black] = ptbl->hung[black]; + hung[white] = ptbl->hung[white]; +#if !defined BAREBONES + EGET++; +#endif + return true; + } + return false; + +} + + +#endif /* CACHE */ + + + + diff --git a/src/uxdsp.c b/src/uxdsp.c new file mode 100644 index 0000000..4afeb1b --- /dev/null +++ b/src/uxdsp.c @@ -0,0 +1,1050 @@ +/* + * uxdsp.c - ALPHA interface for GNU SHOGI + * + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * + * GNU SHOGI is based on GNU CHESS + * + * Copyright (c) 1988,1989,1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * + * This file is part of GNU SHOGI. + * + * GNU Shogi 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 1, or (at your option) + * any later version. + * + * GNU Shogi 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 GNU Shogi; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#if defined MSDOS +#include +#include +#include +#include +#include + +#define ESC 0x1B +#define refresh() fflush(stdout) + +static void param (short n); + +#elif defined THINK_C + +#include +#include + +#define clear() cgotoxy(1,1,stdout),ccleos(stdout) +#define refresh() fflush(stdout) + +#else + +#include +#include +#include +#include + +#endif /* MSDOS */ + +#include "gnushogi.h" + +int mycnt1, mycnt2; + +#define TAB (58) + +#define VIR_C(s) ((flag.reverse) ? 8-column(s) : column(s)) +#define VIR_R(s) ((flag.reverse) ? 8-row(s) : row(s)) + +unsigned short int MV[MAXDEPTH]; +int MSCORE; +char *DRAW; + +void TerminateSearch (int), Die (int); + +void +Initialize (void) +{ + signal (SIGINT, Die); +#if !defined MSDOS && !defined THINK_C + signal (SIGQUIT, Die); + initscr (); + crmode (); +#else + mycnt1 = mycnt2 = 0; +#endif /* MSDOS */ +} + +void +ExitChess (void) +{ +#ifndef NOLIST + ListGame (); +#endif + gotoXY (1, 24); +#if !defined MSDOS && !defined THINK_C + refresh(); + nocrmode (); + endwin (); +#endif /* MSDOS */ + exit (0); +} + +void +Die (int Sig) +{ + char s[80]; + + signal (SIGINT, SIG_IGN); +#if defined MSDOS || defined THINK_C + Sig++; /* shut up the compiler */ +#else + signal (SIGQUIT, SIG_IGN); +#endif /* MSDOS */ + ShowMessage (CP[31]); /*Abort?*/ + scanz ("%s", s); + if (strcmp (s, CP[210]) == 0) /*yes*/ + ExitChess (); + signal (SIGINT, Die); +#if !defined MSDOS && !defined THINK_C + signal (SIGQUIT, Die); +#endif /* MSDOS */ +} + +void +TerminateSearch (int Sig) +{ + signal (SIGINT, SIG_IGN); +#if defined MSDOS || defined THINK_C + Sig++; /* shut up the compiler */ +#else + signal (SIGQUIT, SIG_IGN); +#endif /* MSDOS */ + if (!flag.timeout) + flag.musttimeout = true; + ShowMessage("Terminate Search"); + flag.bothsides = false; + signal (SIGINT, Die); +#if !defined MSDOS && !defined THINK_C + signal (SIGQUIT, Die); +#endif /* MSDOS */ +} +void +ShowLine (short unsigned int *bstline) +{ +} + +void +help (void) +{ + ClrScreen (); + /*printz ("GNU Shogi ??p? command summary\n");*/ + printz (CP[40], version, patchlevel); + printz ("----------------------------------------------------------------\n"); + /*printz ("7g7f move from 7g to 7f quit Exit Chess\n");*/ + printz (CP[158]); + /*printz ("S6h move silver to 6h beep turn %s\n", (flag.beep) ? "off" : "on");*/ + printz (CP[86], (flag.beep) ? CP[92] : CP[93]); + /*printz ("2d2c+ move to 2c and promote\n");*/ + printz (CP[128], (flag.material) ? CP[92] : CP[93]); + /*printz ("P*5e drop a pawn to 5e easy turn %s\n", (flag.easy) ? "off" : "on");*/ + printz (CP[173], (flag.easy) ? CP[92] : CP[93]); + /*printz (" hash turn %s\n", (flag.hash) ? "off" : "on");*/ + printz (CP[174], (flag.hash) ? CP[92] : CP[93]); + /*printz ("bd redraw board reverse board display\n");*/ + printz (CP[130]); + /*printz ("list game to shogi.lst book turn %s used %d of %d\n", (Book) ? "off" : "on", book +count, booksize);*/ + printz (CP[170], (Book) ? CP[92] : CP[93], bookcount, BOOKSIZE); + /*printz ("undo undo last ply remove take back a move\n");*/ + printz (CP[200]); + /*printz ("edit edit board force enter game moves\n");*/ + printz (CP[153]); + /*printz ("switch sides with computer both computer match\n");*/ + printz (CP[194]); + /*printz ("black computer plays black white computer plays white\n");*/ + printz (CP[202]); + /*printz ("depth set search depth clock set time control\n");*/ + printz (CP[149]); + /*printz ("hint suggest a move post turn %s principle variation\n", (flag.post) ? "off" : +"on");*/ + printz (CP[177], (flag.post) ? CP[92] : CP[93]); + /*printz ("save game to file get game from file\n");*/ + printz (CP[188]); + /*printz ("random randomize play new start new game\n");*/ + printz (CP[181]); + gotoXY (10, 20); + printz (CP[47], ColorStr[computer]); + gotoXY (10, 21); + printz (CP[97], ColorStr[opponent]); + gotoXY (10, 22); + printz (CP[79], MaxResponseTime/100); + gotoXY (10, 23); + printz (CP[59], (flag.easy) ? CP[93] : CP[92]); + gotoXY (25, 23); + printz (CP[231], (flag.tsume) ? CP[93] : CP[92]); + gotoXY (40, 20); + printz (CP[52], MaxSearchDepth); + gotoXY (40, 21); + printz (CP[100], (dither) ? CP[93] : CP[92]); + gotoXY (40, 22); + printz (CP[112], (flag.hash) ? CP[93] : CP[92]); + gotoXY (40, 23); + printz (CP[73]); + gotoXY (10, 24); + printz (CP[110], (TCflag) ? CP[93] : CP[92], + TimeControl.moves[black], TimeControl.clock[black] / 100, OperatorTime, MaxSearchDepth); + refresh (); +#ifdef BOGUS + fflush (stdin); /*what is this supposed to do??*/ +#endif /*BOGUS*/ + getchar (); + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); +} + + +static const short x0[2] = {54, 2}; +static const short y0[2] = {20, 4}; + + +static +void +UpdateCatched () + +{ + short side; + for ( side = black; side <= white; side++ ) + { + short x, y, piece, cside, k; + cside = flag.reverse ? (side ^ 1) : side; + x = x0[cside]; + y = y0[cside]; + k = 0; + for ( piece = pawn; piece <= king; piece++ ) + { short n; + if ( n = Captured[side][piece] ) + { gotoXY(x,y); + printz("%i%c",n,pxx[piece]); + if ( cside == black ) y--; else y++; + } + else + k++; + }; + while ( k ) + { k--; + gotoXY(x,y); + printz(" "); + if ( cside == black ) y--; else y++; + } + } + refresh(); +} + + +void +EditBoard (void) + +/* + * Set up a board position. Pieces are entered by typing the piece followed + * by the location. For example, N3f will place a knight on square 3f. + * P* will put a pawn to the captured pieces. + */ + +{ + short a, r, c, sq, i; + char s[80]; + + flag.regularstart = true; + Book = BOOKFAIL; + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); + gotoXY (TAB, 3); + printz (CP[29]); + gotoXY (TAB, 4); + printz (CP[28]); + gotoXY (TAB, 5); + printz (CP[136]); + gotoXY (TAB, 7); + printz (CP[64]); + a = black; + do + { + gotoXY (TAB, 6); + printz (CP[60], ColorStr[a]); /*Editing %s*/ + gotoXY (TAB + 24, 7); + ClrEoln (); + scanz ("%s", s); + if (s[0] == CP[28][0]) /*#*/ + { + for (sq = 0; sq < NO_SQUARES; sq++) + { + board[sq] = no_piece; + color[sq] = neutral; + DrawPiece (sq); + } + ClearCaptured (); + UpdateCatched (); + } + if (s[0] == CP[136][0]) /*c*/ + a = otherside[a]; + if (s[1] == '*') + { + for (i = NO_PIECES; i > no_piece; i--) + if ((s[0] == pxx[i]) || (s[0] == qxx[i])) + break; + Captured[a][unpromoted[i]]++; + UpdateCatched (); + c = -1; + } + else + { + c = '9' - s[1]; + r = 'i' - s[2]; + } + if ((c >= 0) && (c < NO_COLS) && (r >= 0) && (r < NO_ROWS)) + { + sq = locn (r, c); + for (i = NO_PIECES; i > no_piece; i--) + if ((s[0] == pxx[i]) || (s[0] == qxx[i])) + break; + if ( s[3] == '+' ) + i = promoted[i]; + else + i = unpromoted[i]; + board[sq] = i; + color[sq] = ((board[sq] == no_piece) ? neutral : a); + DrawPiece (sq); + } + } while (s[0] != CP[29][0]); /*.*/ + + for (sq = 0; sq < NO_SQUARES; sq++) + Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0); + GameCnt = 0; + Game50 = 1; + ZeroRPT (); + Sdepth = 0; + InitializeStats (); + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); +} + +void +ShowPlayers (void) +{ + gotoXY (5, ((flag.reverse) ? 23 : 2)); + printz ("%s", (computer == white) ? CP[218] : CP[74]); + gotoXY (5, ((flag.reverse) ? 2 : 23)); + printz ("%s", (computer == black) ? CP[218] : CP[74]); +} + +void +ShowDepth (char ch) +{ + gotoXY (TAB, 4); + printz ("Depth= %2d%c", Sdepth, ch); /*Depth= %d%c*/ + ClrEoln (); +} + +void +ShowStage (void) +{ + gotoXY (TAB, 19); + printz("Stage= %2d%c B= %2d W= %2d", + stage,flag.tsume?'T':' ',balance[black],balance[white]); + ClrEoln (); +} + +void +ShowScore (short score) +{ + gotoXY (TAB, 5); + printz (CP[104], score); + ClrEoln (); +} + +void +ShowMessage (char *s) +{ + gotoXY (TAB, 6); + printz ("%s", s); + ClrEoln (); +} + +void +ClearMessage (void) +{ + gotoXY (TAB, 6); + ClrEoln (); +} + +void +ShowCurrentMove (short int pnt, short int f, short int t) +{ + algbr (f, t, false); + gotoXY (TAB, 7); + printz ("(%2d) %5s ", pnt, mvstr[0]); +} + +void +ShowHeader (void) +{ + gotoXY (TAB, 2); + printz (CP[69], version, patchlevel); +} + +void +ShowSidetoMove (void) +{ + gotoXY (TAB, 14); + printz ("%2d: %s", 1 + GameCnt / 2, ColorStr[player]); + ClrEoln (); +} + +void +ShowPrompt (void) +{ + gotoXY (TAB, 17); + printz (CP[121]); /*Your move is?*/ + ClrEoln (); +} + +void +ShowNodeCnt (long int NodeCnt) +{ + gotoXY (TAB, 22); + /* printz (CP[90], NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0); */ + printz ("n=%ld n/s=%ld", NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0); + ClrEoln (); +} + +void +ShowResults (short int score, short unsigned int *bstline, char ch) +{ + unsigned char d, ply; + + if (flag.post) + { + ShowDepth (ch); + ShowScore (score); + d = 7; + for (ply = 1; bstline[ply] > 0; ply++) + { + if (ply % 2 == 1) + { + gotoXY (TAB, ++d); + ClrEoln (); + } + algbr ((short) bstline[ply] >> 8, (short) bstline[ply] & 0xFF, false); + printz ("%5s ", mvstr[0]); + } + ClrEoln (); + while (d < 13) + { + gotoXY (TAB, ++d); + ClrEoln (); + } + } +} + +void +ShowPatternCount (short side, short n) +{ + if (flag.post) + { + gotoXY(TAB+10+3*side,20); + if ( n >= 0 ) + printz("%3d",n); + else + printz(" "); + } +} + +void +ShowGameType (void) +{ + if (flag.post) + { + gotoXY(TAB,20); + printz("%c vs. %c",GameType[black],GameType[white]); + } +} + +void +ShowResponseTime (void) +{ + if (flag.post) + { short TCC=TCcount; + gotoXY(TAB,21); + /* printz("RT=%ld TCC=%d TCL=%ld EX=%ld ET=%ld TO=%d", + ResponseTime,TCC,TCleft,ExtraTime,et,flag.timeout); */ + printz("%ld,%d,%ld,%ld,%ld,%d", + ResponseTime,TCC,TCleft,ExtraTime,et,flag.timeout); + ClrEoln (); + } +} + +void +SearchStartStuff (short int side) +{ + short i; + + signal (SIGINT, TerminateSearch); +#if defined MSDOS || defined THINK_C + side++; /* shut up the compiler */ +#else + signal (SIGQUIT, TerminateSearch); +#endif /* MSDOS */ + for (i = 4; i < 14; i++) + { + gotoXY (TAB, i); + ClrEoln (); + } +} + +void +OutputMove (void) +{ + + UpdateDisplay (root->f, root->t, 0, (short) root->flags); + gotoXY (TAB, 16); + if(flag.illegal){printz(CP[225]);return;} + printz (CP[84], mvstr[0]); /*My move is %s*/ + if (flag.beep) + putchar (7); + ClrEoln (); + + gotoXY (TAB, 18); + if (root->flags & draw) + printz (CP[58]); + else if (root->score == -(SCORE_LIMIT+999)) + printz (CP[95]); + else if (root->score == SCORE_LIMIT+998) + printz (CP[44]); +#ifdef VERYBUGGY + else if (root->score < -SCORE_LIMIT) + printz (CP[96], SCORE_LIMIT+999 + root->score - 1); + else if (root->score > SCORE_LIMIT) + printz (CP[45], SCORE_LIMIT+998 - root->score - 1); +#endif /*VERYBUGGY*/ + ClrEoln (); + if (flag.post) + { + register short h, l, t; + + h = TREE; + l = 0; + t = TREE >> 1; + while (l != t) + { + if (Tree[t].f || Tree[t].t) + l = t; + else + h = t; + t = (l + h) >> 1; + } + + ShowNodeCnt (NodeCnt); + gotoXY (TAB, 23); + printz (CP[81], t); /*Max Tree=*/ + ClrEoln (); + } + ShowSidetoMove (); +} + +void +UpdateClocks (void) +{ + short m, s; + long dt; + + if (TCflag) + { + m = (short) ((dt = (TimeControl.clock[player] - et)) / 6000); + s = (short) ((dt - 6000 * (long) m) / 100); + } + else + { + m = (short) ((dt = et) / 6000); + s = (short) (et - 6000 * (long) m) / 100; + } + if (m < 0) + m = 0; + if (s < 0) + s = 0; + if (player == black) + gotoXY (20, (flag.reverse) ? 2 : 23); + else + gotoXY (20, (flag.reverse) ? 23 : 2); + /* printz ("%d:%02d %ld ", m, s, dt); */ + printz ("%d:%02d ", m, s); + if (flag.post) + ShowNodeCnt (NodeCnt); + refresh (); +} + +void +gotoXY (short int x, short int y) +{ +#if defined MSDOS + putchar (ESC); + putchar ('['); + param (y); + putchar (';'); + param (x); + putchar ('H'); +#elif defined THINK_C + cgotoxy (x, y, stdout); +#else + move (y - 1, x - 1); +#endif /* MSDOS */ +} + +void +ClrScreen (void) +{ +#ifdef MSDOS + putchar (ESC); + putchar ('['); + putchar ('2'); + putchar ('J'); +#else + clear (); +#endif /* MSDOS */ + refresh (); +} + +void +ClrEoln (void) +{ +#ifdef MSDOS + putchar (ESC); + putchar ('['); + putchar ('K'); +#elif defined THINK_C + ccleol (stdout); +#else + clrtoeol (); +#endif /* MSDOS */ + refresh (); +} + +#ifdef MSDOS +void +param (short n) +{ + if (n >= 10) + { + register short d, q; + + q = n / 10; + d = n % 10; + putchar (q + '0'); + putchar (d + '0'); + } + else + putchar (n + '0'); +} + +#endif /* MSDOS */ + +void +DrawPiece (short int sq) +{ + register char x, y; + + char piece,l,r,p; + +#if defined(MSDOS) && !defined(SEVENBIT) + if (color[sq] == white) + x = '7'; /* print WHITE boldface, */ + else + x = '1'; /* print BLACK inverted */ + piece = board[sq]; + if ( is_promoted[piece] ) { + p = '+'; y = pxx[unpromoted[piece]]; + } else { + p = ' '; y = pxx[piece]; + }; + gotoXY (8 + 5 * VIR_C (sq), 4 + 2 * (8 - VIR_R (sq))); + printz ("\033[%cm%c%c\033[0m", x, p, y); +#else + if ( color[sq]==neutral ) + l = r = ' '; + else if ( flag.reverse ^ (color[sq]==black) ) { + l = '/'; r = '\\'; + } else { + l = '\\', r = '/'; + }; + piece = board[sq]; + if ( is_promoted[piece] ) { + p = '+'; y = pxx[unpromoted[piece]]; + } else { + p = ' '; y = pxx[piece]; + }; + gotoXY (8 + 5 * VIR_C (sq), 4 + 2 * (8 - VIR_R (sq))); + printz ("%c%c%c%c", l, p, y, r); +#endif +} + +void +ShowPostnValue (short int sq) + +/* + * must have called ExaminePosition() first + */ + +{ + short score; + + gotoXY (4 + 5 * VIR_C (sq), 5 + 2 * (7 - VIR_R (sq))); + score = ScorePosition (color[sq]); + if (color[sq] != neutral) +#if defined SAVE_SVALUE + printz ("??? "); +#else + printz ("%3d ", svalue[sq]); +#endif + else + printz (" "); +} + +void +ShowPostnValues (void) +{ + short sq, score; + + ExaminePosition (opponent); + for (sq = 0; sq < NO_SQUARES; sq++) + ShowPostnValue (sq); + score = ScorePosition (opponent); + gotoXY (TAB, 5); + printz (CP[103], score, + mtl[computer], pscore[computer], GameType[computer], + mtl[opponent], pscore[opponent], GameType[opponent]); + + ClrEoln (); +} + + +void +UpdateDisplay (short int f, short int t, short int redraw, short int isspec) +{ + short i, sq, z; + + if (redraw) + { + ShowHeader (); + ShowPlayers (); + + i = 2; + gotoXY (3, ++i); +#if defined(MSDOS) && !defined(SEVENBIT) + printz ("\332\304\304\304\304\302\304\304\304\304\302\304\304\304\304" \ + "\302\304\304\304\304\302\304\304\304\304\302\304\304\304\304" \ + "\302\304\304\304\304\302\304\304\304\304\277"); +#else + printz (" +----+----+----+----+----+----+----+----+----+"); +#endif /* MSDOS && !SEVENBIT */ + while (i < 20) + { + gotoXY (1, ++i); + if (flag.reverse) + z = (i / 2) - 1; + else + z = 11 - ((i+1) / 2); +#if defined(MSDOS) && !defined(SEVENBIT) + printz ("%d \263 \263 \263 \263 \263 \263 " \ + "\263 \263 \263", z); +#else + printz (" %c | | | | | | | | | |", 'a'+9-z); +#endif /* MSDOS && !SEVENBIT */ + gotoXY (3, ++i); + if (i < 20) +#if defined(MSDOS) && !defined(SEVENBIT) + printz ("\303\304\304\304\304\305\304\304\304\304\305\304\304" \ + "\304\304\305\304\304\304\304\305\304\304\304\304\305" \ + "\304\304\304\304\305\304\304\304\304\305\304\304\304" \ + "\304\264"); +#else + printz (" +----+----+----+----+----+----+----+----+----+"); +#endif /* MSDOS && !SEVENBIT */ + } +#if defined(MSDOS) && !defined(SEVENBIT) + printz ("\300\304\304\304\304\301\304\304\304\304\301\304\304\304\304" \ + "\301\304\304\304\304\301\304\304\304\304\301\304\304\304\304" \ + "\301\304\304\304\304\301\304\304\304\304\331"); +#else + printz (" +----+----+----+----+----+----+----+----+----+"); +#endif /* MSDOS && !SEVENBIT */ + gotoXY (3, 22); + printz(" "); + if (flag.reverse) + printz (CP[16]); + else + printz (CP[15]); + for (sq = 0; sq < NO_SQUARES; sq++) + DrawPiece (sq); + } + else /* not redraw */ + { + if ( f < NO_SQUARES ) + DrawPiece (f); + DrawPiece (t & 0x7f); + } + if ( (isspec & capture) || (isspec & dropmask) || redraw ) + { short side; + for ( side = black; side <= white; side++ ) + { short x, y, piece, cside, k; + cside = flag.reverse ? (side ^ 1) : side; + x = x0[cside]; + y = y0[cside]; + k = 0; + for ( piece = pawn; piece <= king; piece++ ) + { short n; + if ( n = Captured[side][piece] ) + { gotoXY(x,y); + printz("%i%c",n,pxx[piece]); + if ( cside == black ) y--; else y++; + } + else + k++; + }; + while ( k ) + { k--; + gotoXY(x,y); + printz(" "); + if ( cside == black ) y--; else y++; + } + } + } + refresh (); +} + +extern char *InPtr; + +void +ChangeAlphaWindow (void) +{ + ShowMessage (CP[114]); + scanz ("%hd", &WAwindow); + ShowMessage (CP[34]); + scanz ("%hd", &BAwindow); +} + +void +ChangeBetaWindow (void) +{ + ShowMessage (CP[115]); + scanz ("%hd", &WBwindow); + ShowMessage (CP[35]); + scanz ("%hd", &BBwindow); +} + +void +GiveHint (void) +{ + char s[40]; + if (hint) + { + algbr ((short) (hint >> 8), (short) (hint & 0xFF), false); + strcpy (s, CP[198]); /*try*/ + strcat (s, mvstr[0]); + ShowMessage (s); + } + else + ShowMessage (CP[223]); +} + +void +ChangeHashDepth (void) +{ + ShowMessage (CP[163]); + scanz ("%hd", &HashDepth); + ShowMessage (CP[82]); + scanz ("%hd", &HashMoveLimit); +} + +void +ChangeSearchDepth (void) +{ + ShowMessage (CP[150]); + scanz ("%hd", &MaxSearchDepth); + TCflag = !(MaxSearchDepth > 0); +} + +void +SetContempt (void) +{ + ShowMessage (CP[142]); + scanz ("%hd", &contempt); +} + +void +ChangeXwindow (void) +{ + ShowMessage (CP[208]); + scanz ("%hd", &xwndw); +} + +void +SelectLevel (char *sx) +{ + int item; + + ClrScreen (); + gotoXY (32, 2); + printz (CP[41], version, patchlevel); + gotoXY (20, 4); + printz (CP[18]); + gotoXY (20, 5); + printz (CP[19]); + gotoXY (20, 6); + printz (CP[20]); + gotoXY (20, 7); + printz (CP[21]); + gotoXY (20, 8); + printz (CP[22]); + gotoXY (20, 9); + printz (CP[23]); + gotoXY (20, 10); + printz (CP[24]); + gotoXY (20, 11); + printz (CP[25]); + gotoXY (20, 12); + printz (CP[26]); + gotoXY (20, 13); + printz (CP[27]); + + OperatorTime = 0; + TCmoves = 40; + TCminutes = 5; + TCseconds = 0; + + gotoXY (20, 17); + printz (CP[62]); + refresh (); + scanz ("%d", &item); + switch (item) + { + case 1: + TCmoves = 40; + TCminutes = 5; + break; + case 2: + TCmoves = 40; + TCminutes = 15; + break; + case 3: + TCmoves = 40; + TCminutes = 30; + break; + case 4: + TCmoves = 80; + TCminutes = 15; + flag.gamein = true; + break; + case 5: + TCmoves = 80; + TCminutes = 30; + flag.gamein = true; + break; + case 6: + TCmoves = 80; + TCminutes = 15; + TCadd = 3000; + flag.gamein = true; + break; + case 7: + TCmoves = 80; + TCminutes = 30; + TCadd = 3000; + break; + case 8: + TCmoves = 1; + TCminutes = 1; + flag.onemove = true; + break; + case 9: + TCmoves = 1; + TCminutes = 15; + flag.onemove = true; + break; + case 10: + TCmoves = 1; + TCminutes = 30; + flag.onemove = true; + break; + } + + TCflag = (TCmoves > 0); + + TimeControl.clock[black] = TimeControl.clock[white] = 0; + + SetTimeControl (); + ClrScreen (); + UpdateDisplay (0, 0, 1, 0); +} + +void +DoDebug (void) +{ + short c, p, sq, tp, tc, tsq, score; + char s[40]; + + ExaminePosition (opponent); + ShowMessage (CP[65]); + scanz ("%s", s); + c = neutral; + if (s[0] == CP[9][0] || s[0] == CP[9][1]) /*b B*/ + c = black; + if (s[0] == CP[9][2] || s[0] == CP[9][3]) /*w W*/ + c = white; + for (p = king; p > no_piece; p--) + if ((s[1] == pxx[p]) || (s[1] == qxx[p])) + break; + for (sq = 0; sq < NO_SQUARES; sq++) + { + tp = board[sq]; + tc = color[sq]; + board[sq] = p; + color[sq] = c; + tsq = PieceList[c][1]; + PieceList[c][1] = sq; + ShowPostnValue (sq); + PieceList[c][1] = tsq; + board[sq] = tp; + color[sq] = tc; + } + score = ScorePosition (opponent); + gotoXY (TAB, 5); + printz (CP[103], score, + mtl[computer], pscore[computer], GameType[computer], + mtl[opponent], pscore[opponent], GameType[opponent]); + + ClrEoln (); +} + +void +DoTable (short table[NO_SQUARES]) +{ + short sq; + ExaminePosition (opponent); + for (sq=0;sq