[gcompris/gcomprixogoo] Added a copy of gnome-gnuchess internally since the regular gnuchess crashes on macosx. This is acti
- From: Bruno Coudoin <bcoudoin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcompris/gcomprixogoo] Added a copy of gnome-gnuchess internally since the regular gnuchess crashes on macosx. This is acti
- Date: Thu, 8 Apr 2010 22:47:40 +0000 (UTC)
commit 369c866b4888a53758e71db553aaca0044e06d41
Author: Bruno Coudoin <bruno ordinateur-de-bruno-coudoin local>
Date: Fri Apr 9 00:36:52 2010 +0200
Added a copy of gnome-gnuchess internally since the regular gnuchess crashes on macosx.
This is activated only on MacOSX.
configure.ac | 8 +-
macosx/gcompris.bundle | 2 +-
src/chess_computer-activity/Makefile.am | 4 +
src/chess_computer-activity/gnuchess/Makefile.am | 12 +
src/chess_computer-activity/gnuchess/README | 512 +++
src/chess_computer-activity/gnuchess/atak.c | 536 ++++
src/chess_computer-activity/gnuchess/book.c | 693 ++++
src/chess_computer-activity/gnuchess/book.h | 35 +
src/chess_computer-activity/gnuchess/cmd.c | 995 ++++++
src/chess_computer-activity/gnuchess/common.h | 860 +++++
src/chess_computer-activity/gnuchess/debug.c | 74 +
src/chess_computer-activity/gnuchess/epd.c | 370 +++
src/chess_computer-activity/gnuchess/eval.c | 1496 +++++++++
src/chess_computer-activity/gnuchess/eval.h | 118 +
src/chess_computer-activity/gnuchess/genmove.c | 788 +++++
src/chess_computer-activity/gnuchess/getopt.c | 1067 +++++++
src/chess_computer-activity/gnuchess/getopt.h | 179 ++
src/chess_computer-activity/gnuchess/getopt1.c | 187 ++
.../gnuchess/gnome-gnuchess | Bin 0 -> 245180 bytes
src/chess_computer-activity/gnuchess/hash.c | 127 +
src/chess_computer-activity/gnuchess/hung.c | 76 +
src/chess_computer-activity/gnuchess/init.c | 796 +++++
src/chess_computer-activity/gnuchess/inlines.h | 61 +
src/chess_computer-activity/gnuchess/input.c | 192 ++
src/chess_computer-activity/gnuchess/iterate.c | 375 +++
src/chess_computer-activity/gnuchess/lexpgn.c | 3348 ++++++++++++++++++++
src/chess_computer-activity/gnuchess/lexpgn.h | 27 +
src/chess_computer-activity/gnuchess/main.c | 471 +++
src/chess_computer-activity/gnuchess/move.c | 939 ++++++
src/chess_computer-activity/gnuchess/null.c | 77 +
src/chess_computer-activity/gnuchess/output.c | 303 ++
src/chess_computer-activity/gnuchess/pgn.c | 390 +++
src/chess_computer-activity/gnuchess/players.c | 212 ++
src/chess_computer-activity/gnuchess/ponder.c | 58 +
src/chess_computer-activity/gnuchess/quiesce.c | 114 +
src/chess_computer-activity/gnuchess/random.c | 135 +
src/chess_computer-activity/gnuchess/repeat.c | 45 +
src/chess_computer-activity/gnuchess/search.c | 734 +++++
src/chess_computer-activity/gnuchess/solve.c | 78 +
src/chess_computer-activity/gnuchess/sort.c | 345 ++
src/chess_computer-activity/gnuchess/swap.c | 170 +
src/chess_computer-activity/gnuchess/test.c | 266 ++
src/chess_computer-activity/gnuchess/ttable.c | 162 +
src/chess_computer-activity/gnuchess/util.c | 220 ++
src/chess_computer-activity/gnuchess/version.h | 27 +
45 files changed, 17681 insertions(+), 3 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c508639..23c8e8e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -299,6 +299,7 @@ if test "x$platform_win32" = "xyes" ; then
dnl Test for gnuchess
AC_DEFINE_UNQUOTED(GNUCHESS, "gnuchess.exe", Defines where GNU Chess resides on the system)
+ build_gnuchess=yes
if test x$disable_activation_code = xno; then
AC_DEFINE([ACTIVATION_CODE], 1,[Activation code is enabled])
@@ -328,7 +329,8 @@ elif test "x$nsbundle" = "xyes" ; then
AC_DEFINE_UNQUOTED(SYSTEM_CONFIG_DIR, "../Resources/etc", [System GCompris config directory])
dnl Test for gnuchess
- AC_DEFINE_UNQUOTED(GNUCHESS, "../Resources/bin/gnuchess", Defines where GNU Chess resides on the system)
+ AC_DEFINE_UNQUOTED(GNUCHESS, "../Resources/bin/gcompris-gnuchess", Defines where GNU Chess resides on the system)
+ build_gnuchess=yes
if test x$disable_activation_code = xno; then
AC_DEFINE([ACTIVATION_CODE], 1,[Activation code is enabled])
@@ -361,8 +363,9 @@ else
AC_MSG_ERROR(Couldn't find gnuchess, please install the gnuchess package version 5 or above)
fi
AC_DEFINE_UNQUOTED(GNUCHESS, "$GNUCHESS", Defines where GNU Chess resides on the system)
-
+ build_gnuchess=no
fi
+AM_CONDITIONAL(BUILD_GNUCHESS, test x$build_gnuchess != xno)
AC_PATH_PROG(TEXINFO, makeinfo,no)
if test x$TEXINFO = xno; then
@@ -628,6 +631,7 @@ src/chat-activity/Makefile
src/chess_computer-activity/Makefile
src/chess_computer-activity/resources/Makefile
src/chess_computer-activity/resources/chess/Makefile
+src/chess_computer-activity/gnuchess/Makefile
src/chess_movelearn-activity/Makefile
src/chess_partyend-activity/Makefile
src/chronos-activity/Makefile
diff --git a/macosx/gcompris.bundle b/macosx/gcompris.bundle
index a06f85c..a6c2f6c 100644
--- a/macosx/gcompris.bundle
+++ b/macosx/gcompris.bundle
@@ -79,7 +79,7 @@
</binary>
<binary>
- ${prefix}/bin/gnuchess
+ ${prefix}/bin/gcompris-gnuchess
</binary>
<binary>
diff --git a/src/chess_computer-activity/Makefile.am b/src/chess_computer-activity/Makefile.am
index 28f5e22..0748db2 100644
--- a/src/chess_computer-activity/Makefile.am
+++ b/src/chess_computer-activity/Makefile.am
@@ -1,4 +1,8 @@
+if BUILD_GNUCHESS
+SUBDIRS = resources gnuchess
+else
SUBDIRS = resources
+endif
if PLATFORM_WIN32
shared = -shared
diff --git a/src/chess_computer-activity/gnuchess/Makefile.am b/src/chess_computer-activity/gnuchess/Makefile.am
new file mode 100644
index 0000000..d59a7ea
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS = gcompris-gnuchess
+
+gcompris_gnuchess_SOURCES = atak.c book.c cmd.c debug.c epd.c eval.c genmove.c \
+ getopt.c getopt1.c hash.c\
+ hung.c init.c input.c iterate.c main.c move.c null.c output.c players.c\
+ pgn.c ponder.c quiesce.c random.c repeat.c search.c solve.c sort.c\
+ swap.c test.c ttable.c util.c common.h book.h eval.h getopt.h \
+ inlines.h version.h lexpgn.c lexpgn.h
+
+gcompris_gnuchess_CFLAGS = $(PTHREAD_CFLAGS) $(AM_CFLAGS)
+
+gcompris_gnuchess_LDFLAGS = $(PTHREAD_LDFLAGS) $(PTHREAD_LIBS) $(AM_LDFLAGS)
diff --git a/src/chess_computer-activity/gnuchess/README b/src/chess_computer-activity/gnuchess/README
new file mode 100644
index 0000000..c2f39f7
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/README
@@ -0,0 +1,512 @@
+README
+GNU CHESS 5
+by Stuart Cracraft <cracraft gnu org>
+copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
+1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Modified Simon Waters <simon wretched demon co uk> 2001
+Modified Simon Waters <simon wretched demon co uk> 2003
+
+IMPORTANT: Please send all updates to Simon at the above address.
+
+Table of Contents
+
+ Introduction
+ Who We Are
+ Data Structures
+ Move Generator
+ Search
+ Evaluation
+ Book
+ Hash Table
+ Auxillary File Formats (PGN, EPD)
+ Universal Board
+ Caveats
+ Compilers
+ Internet
+ Xboard/Winboard
+ Command List
+
+
+INTRODUCTION
+
+Welcome to the GNU CHESS 5 README. This is somewhat different than
+a normal readme. You might consider this a manual. We've always found
+multiple documents confusing, overlapping and sometimes contradictory
+as far as software documentation goes. By putting it all together in
+one place we hope to avoid these traditional inadequacies and be able
+to maintain a single document. If you add documentation, add it to
+this document only.
+
+GNU Chess 5 is the new version of GNU Chess. The goal of creating this
+new version was to eliminate perceived problems with past versions, the
+major one being spaghetti-code that was extremely poorly documented, but
+another being antiquated data structures and especially the ignominous
+linked list. Another good reason was to have more standard file formats
+for game positions and game listings.
+
+
+WHO WE ARE
+
+We are the GNU Chess developers and you may reach us at
+
+ bug-gnu-chess gnu org
+
+We are indebted to our sponsor, the Free Software Foundation
+whose web page is:
+
+ http://www.gnu.org
+
+and which also serves as our software depository for new versions of
+GNU and GNU Chess.
+
+We also have a Usenet bulletin board, gnu.chess. Feel free to post and
+support. Please become a developer and contribute your time and coding skill
+to GNU Chess. Make a donation of your time and money.
+
+But, as developers we like to develop our own ideas. Thus, if you have
+an idea check to see that no one else is working on it (posting on the
+above bulletin board or sending an email should be sufficient to find
+if someone is working on the idea and if you can collaborate with
+them.)
+
+We don't like messages asking us to implement features. Everybody
+has a list a mile long. Instead, contribute by writing code or pointing
+out very clearly a bug. To report a bug, tell us the version number
+of the program ("./gnuchess --version").
+
+The code is provided for the purpose of encouraging you to do the
+programming. If you lack the programming skills to do so, try
+dabbling in it. You might surprise yourself.
+
+
+DATA STRUCTURES
+
+The primary data structure of GNU Chess is the bitboard. A bitboard
+is a 64-bit GNU C long long. It represents characteristics of a position.
+For example, 12 bitboards are sufficient to describe the whereabouts
+of all the pieces for both sides, i.e.
+
+ BitBoard board.b[2][6];
+
+So for example with a knight equal to 2 and white equal to 0 all the
+knights are located by the reference
+
+ #define white 0
+ #define knight 2
+
+ ... board.b[white][knight] ...
+
+Testing whether a particular square has a knight on it could be done
+with
+
+ if (BitBoard[B1] & board.b[white][knight]) { ... }
+
+Another set of move arrays is helpful for calculating the simple moves
+of a knight or a king
+
+ MoveArray[knight or king][sq]
+
+This returns a bitmap of the squares from which a knight or king
+could move from the square sq. Squares are based at 0 for a1 (White's
+queen's rook 1) and numbered left to right up until 63 for h8 (Black's
+king's rook 1).
+
+Another basic data structure is the board. It is defined in common.h
+as the Board typedef:
+
+ typedef struct
+ {
+ BitBoard b[2][7]; /* Pieces by side (0 - white, 1 black
+ by piece (1 - pawn ... 6 - king */
+ BitBoard friend[2]; /* Friendly (this side's) pieces */
+ BitBoard blocker; /* Enemy pieces */
+ BitBoard blockerr90;
+ BitBoard blockerr45;
+ BitBoard blockerr315;
+ short ep; /* Location of en passant square */
+ short flag; /* Relevant flags relating to castle privs */
+ short side; /* Color of side on move 0 - white 1 - black */
+ short material[2]; /* Total material by side not inc. king */
+ short pmaterial[2]; /* Total pawn material by side not inc. king */
+ short castled[2]; /* True (1) if side is castled */
+ short king[2]; /* Location of king 0 - a1 .. 63 - h8 */
+ } Board;
+
+Basic data structure typedefs are defined in common.h and allocated in
+main.c for the most part. Please read and understand those files. The
+best way to understand data structures is to add new evaluation terms.
+
+MOVE GENERATOR
+
+This is a rotated bit-board method which is considered state-of-the-art
+currently.
+
+SEARCH
+
+Based on Professor Tony Marsland's modification to alpha-beta minimax,
+called Principal Variation Search (PVS), this algorithm performs credibly.
+
+EVALUATION
+
+Evaluation in this version is quite a bit different than before.
+Earlier versions used piece/square tables with some end-leaf
+evaluation (but primary pc/sq tables). These are tables filled with
+values regarding the importance of having pieces on particular squares.
+It was filled once, at the beginning of the search.
+
+The drawback of pc/sq tables is that the information is typically of
+less and less importance the deeper a program searches because the
+board changes so much. With computers getting faster and faster, deeper
+and deeper searches are possible and so the pc/sq tables can provide
+misleading direction to the program, resulting in anti-positional moves.
+
+More recently there has been a return by some to what we espouse here:
+full end-leaf evaluation. Further, we use bitboards (64-bit quantities)
+to represents characteristics of the board. This harkens back, ironically
+to the early days of computer chess when giant number-crunching machines
+back in the 60's used bitmaps to describe positions.
+
+Bitboards in this version of GNU are defined using the "BitBoard" typedef
+defined in common.h. main.c contains most of the bitboards and these
+are accessed and used throughout the program and particularly by
+the move generator and the evaluator.
+
+The evaluator in eval.c consists of a series of scoring routines like
+ScoreP (), ScoreN (), ScoreB (), corresponding to the piece being
+scored. The routine evaluates all pieces of that type (P - pawn,
+N - knight, B - bishop, etc.) on the current board and returns a
+score.
+
+Typically a loop is used of the form
+
+ short sq; /* Location of the piece of this type */
+ short s; /* Score value for all pieces
+ BitBoard b; /* Stores the bitboard representing location of the piece */
+ s = 0; /* Score starts out as zero */
+ b = board.b[side][knight];
+ while (b) {
+ sq = leadz(b);
+ CLEARBIT (b, sq);
+ if (piece on sq has some property)
+ s += SOME_BONUS_OR_PENALTY; /* defined in eval.h */
+ }
+ return(s);
+
+As you can see, this routine locates each piece in the 64-bit map
+where the corresponding square of the 64 is set to 1 meaning a piece
+is there. Hence for example in the opening position, board.b[white][bishop]
+would have the 3rd and 7th low-order bits set corresponding to the original
+locations of bishops in a game on C1 and F1. Likewise the values
+BitPosArray[C1] and BitPosArray[F1] can be used to return 64-bit
+quantities for checking specific matches as in
+
+ if (BitPosArray[A1] & board.b[side][bishop])
+ s += SOME_VERY_NEGATIVE_PENALTY_FOR_BISHOP_IN_A1_CORNER
+
+Writing evaluation code comes very naturally using these methods. Try
+to avoid too many specific square checks as those are expensive. Ideas
+as shown in the CTL() routine can be used to check for piece placement
+on specific squares being advantageous or disadvantageous.
+
+Primary evaluation is done with Evaluate(). Certain specifics are
+calculated which are deemed very important such as king evaluation
+and pawn evaluation. Then a "lazy evaluation" scenario is checked
+for which can save time. Otherwise other pieces are also evaluated.
+
+Very important for evaluation is the ability to see what board you
+are evaluating. Typically this should be sufficient when you add
+the new term:
+
+ /* ... new logic ... */
+ {
+ s += SOME_NEW_BONUS (define in eval.h)
+ printf("The condition is triggered:\n");
+ ShowBoard ();
+ getchar();
+ }
+
+This lets you see the board at the point the condition is triggered
+which adds the bonus or penalty to the evaluation score.
+
+
+BOOK
+
+The opening book is implemented as a simple binary file consisting of
+a set of sequential records of struct hashtype as defined in the module
+book.c. This data structure is simply two part, a 64-bit HashType (see
+common.h) and a 32-bit score.
+
+The binary book stored in book.dat is compiled from the file book.pgn
+using the command "book add book.pgn" into a sequential set of binary
+records in the format as described above. book.pgn is simply a set of
+game records in portable game notation format. A set of master games
+may be used or specific openings programmed this way for a user-changeable
+opening book.
+
+HASH TABLE
+
+The hash table is simply an area of memory where information about
+positions is stored. In this version of the program there are two
+types of hash tables: general and pawn.
+
+The general hash table size is controlled by the variable HASHSLOTS
+as defined in common.h. Likewise the pawn hash table size is controlled
+by the variable PAWNSLOTS in common.h.
+
+The number of hashtable slots can be controlled from the command
+line (Type "gnuchess -help" for details), or via the interactive
+hashsize command.
+
+Typically middle-game searches are sped up by 25%-50% by the general
+hash table and by much more in endgames where there are few pieces
+(because so many of the positions turn out to be cached already in
+the hash table.)
+
+Pawn evaluation is traditionally expensive because there are so many
+things to evaluate. The pawn hash table remembers all the different
+pawn structures in the search. Typically pawn structure evaluation
+(without reference to pieces) may be calculated by simple table
+lookup this way 90-99% of the time. Hence, any amount of pawn logic
+that is pure-pawn and not related to pieces may be added without guilt.
+On the other hand, pawn structure that relates to pieces must be
+recalculated for every position. See ScoreP() in eval.c
+
+
+AUXILLARY FILE FORMATS
+
+.dat - binary book format, simply a 64-bit position hash and a 32-bit score
+.pgn - game listing like 1. e4 e5 2. Nf3 etc.
+.epd - epd-style format using FEN notation. See tests subdirectory for example.
+log.nnn - record of an entire game from computer's viewpoint (thinking, etc.)
+game.nnn - record of an entire game, similar to .pgn but auto-generated
+
+The .dat file format is a simple binary format for the compiled book
+which is read by the program when it is using book. See the section BOOK
+for more detail.
+
+EPD and PGN require little introduction. These are the uniformly accepted
+standards for position recording and game recording.
+
+Note that log.nnn and game.nnn files are written at the end of a game
+when you use the "name" command to give the computer your name. It is
+highly recommended to do this since the resulting two files that match
+in a monotonically-increasing extension numbered suffix may be used for
+reporting bugs and keeping track of your games.
+
+
+COMPILERS
+
+ We like GNU C in all its various forms. For Unix and Linux, use GNU C.
+
+ For Microsoft Windows platforms we compile and test using Cygwin,
+ which is a port of many GNU packages, including GCC.
+
+ Cygwin may require specific run time DLL's to provide the interface,
+ these should be provided with any executable you receive.
+
+ Whilst GCC is the supported compiler, a key goal is portability. If
+ you experience problems compiling GNU Chess with a modern C compiler
+ please let the developers know.
+
+INTERNET
+
+ GNU CHESS 5 has been tested substantially on the Free Internet Chess
+ Servers (freechess.org) with Xboard (See Zippy documentation in the
+ Xboard/Winboard distribution http://www.tim-mann.org/).
+
+ GNU Chess 5.06 and later should also operate with icsDrone. Testing
+ 5.06 with icsDrone 1.5.0 showed no immediate issues.
+
+XBOARD/WINBOARD
+
+ Running the program with the "--xboard" command line parameter sets it
+ to produce output acceptable to and accept input suitable for xboard
+ and winboard, the graphical display front-ends with mouse interface.
+
+ For historical reasons the option "xboard" does not need to be
+ preceeded by "--", however we would encourage the new syntax.
+
+COMMAND LIST
+
+ ^C
+ Typically the interrupt key stops a search in progress,
+ makes the move last considered best and returns to the
+ command prompt
+
+ quit
+ Quit the program.
+ exit
+ In analysis mode this stops analysis, otherwise it quits the program.
+
+ help
+ Produces a help blurb corresponding to this list of commands.
+
+ usage
+ Produce blurb on command line options.
+ (Same as "gnuchess --help")
+
+ book
+ add - compiles book.dat from book.pgn
+ on - enables use of book
+ off - disables use of book
+ best - play best move from book
+ worst - play worst move from book
+ random - play any move from book
+
+ prefer (default) - choose a good move from book
+ (Method subject to variation)
+
+ version
+ prints out the version of this program
+ (Same as "gnuchess --version")
+
+ pgnsave FILENAME
+ saves the game so far to the file from memory
+
+ pgnload FILENAME
+ loads the game in the file into memory
+
+ force
+ manual
+ Makes the program stop moving. You may now enter moves
+ to reach some position in the future.
+ (Same as "gnuchess --manual")
+
+ white
+ Program plays black, set white to move.
+
+ black
+ Program plays white, set black to move.
+
+ (White and black commands are mainly for icsDrone
+ and will cause the current en-passant capture
+ square to be forgotten).
+
+ go
+ Computer takes whichever side is on move and begins its
+ thinking immediately
+
+ easy
+ Disables thinking on opponent's time
+ (Same as "gnuchess --easy").
+
+ hard
+ Enables thinking on opponent's time
+
+ post
+ Arranges for verbose thinking output showing variation, score,
+ time, depth, etc.
+
+ If pondering (see hard) is on, the program will output
+ it's thinking whilst the opponent is thinking.
+
+ (Also "gnuchess --post")
+
+ nopost
+ Turns off verbose thinking output
+
+ name NAME
+ Lets you input your name. Also writes the log.nnn and a
+ corresponding game.nnn file. For details please see
+ auxillary file format sections.
+
+ result
+ Mostly used by Internet Chess server.
+
+ activate
+
+ This command reactivates a game that has been terminated automatically
+ due to checkmate or no more time on the clock. However, it does not
+ alter those conditions. You would have to undo a move or two or
+ add time to the clock with level or time in that case.
+
+ rating COMPUTERRATING OPPONENTRATING
+ Inputs the estimated rating for computer and for its opponent
+
+ new
+ Sets up new game (i.e. positions in original positions)
+
+ time
+ Inputs time left in game for computer in hundredths of a second.
+ Mostly used by Internet Chess server.
+
+ otim (NOT IMPLEMENTED)
+ Mostly used by Internet Chess server.
+
+ random (NOT IMPLEMENTED)
+ Randomizes play by perturbing the evaluation score slightly.
+ The degree of perturbation is adjustable.
+
+ hash
+ on - enables using the memory hash table to speed search
+ off - disables the memory hash table
+
+ hashsize N
+ Sets the hash table to permit storage of N positions
+ N is rounded down to nearest power of 2.
+ (Also "gnuchess --hashsize=N")
+
+ null
+ on - enables using the null move heuristic to speed search
+ off - disables using the null move heuristic
+
+ xboard
+ on - enables use of xboard/winboard
+ off - disables use of xboard/winboard
+ (Also "gnuchess --xboard")
+
+ depth N
+ Sets the program to look N ply (half-moves) deep for every
+ search it performs. If there is a checkmate or other condition
+ that does not allow that depth, then it will not be
+
+ level MOVES MINUTES INCREMENT
+ Sets time control to be MOVES in MINUTES with each move giving
+ an INCREMENT (in seconds, i.e. Fischer-style clock).
+
+ load
+ epdload
+ Loads a position in EPD format from disk into memory.
+
+ save
+ epdsave
+ Saves game position into EPD format from memory to disk.
+
+ switch
+ Switches side to move
+
+ solve FILENAME
+ solveepd FILENAME
+ Solves the positions in FILENAME
+
+ remove
+ Backs up two moves in game history
+
+ undo
+ Backs up one move in game history
+
+ show
+ board - displays the current board
+ time - displays the time settings
+ moves - shows all moves using one call to routine
+ escape - shows moves that escape from check using one call to routine
+ noncapture - shows non-capture moves
+ capture - shows capture moves
+ eval [or score] - shows the evaluation per piece and overall
+ game - shows moves in game history
+ pin - shows pinned pieces
+
+ test
+ movelist - reads in an epd file and shows legal moves for its entries
+ capture - reads in an epd file and shows legal captures for its entries
+ movegenspeed - tests speed of move generator
+ capturespeed - tests speed of capture move generator
+ eval - reads in an epd file and shows evaluation for its entries
+ evalspeed tests speed of the evaluator
+
+ analyze
+ Switches program into analysis mode, this is primarily intended for
+ communicating analysis to an external interface using the Xboard
+ chess engine protocol. It enables "force", "post", and
+ "hard", at the same time, whilst altering the
+ output format of post to conform with the engine protocol.
diff --git a/src/chess_computer-activity/gnuchess/atak.c b/src/chess_computer-activity/gnuchess/atak.c
new file mode 100644
index 0000000..c94441d
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/atak.c
@@ -0,0 +1,536 @@
+/* GNU Chess 5.0 - atak.c - attack code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+
+
+short SqAtakd (short sq, short side)
+/**************************************************************************
+ *
+ * To determine if sq is attacked by any pieces from side.
+ *
+ **************************************************************************/
+{
+ register BitBoard *a, b, *c, d, blocker;
+ int t;
+
+ a = board.b[side];
+
+ /* Knights */
+ if (a[knight] & MoveArray[knight][sq])
+ return (true);
+
+ /* Kings */
+ if (a[king] & MoveArray[king][sq])
+ return (true);
+
+ /* Pawns */
+ if (a[pawn] & MoveArray[ptype[1^side]][sq])
+ return (true);
+
+ c = FromToRay[sq];
+ blocker = board.blocker;
+
+ /* Bishops & Queen */
+ b = (a[bishop] | a[queen]) & MoveArray[bishop][sq];
+ d = ~b & blocker;
+ while (b)
+ {
+ t = leadz (b);
+ if (!(c[t] & d))
+ return (true);
+ CLEARBIT (b, t);
+ }
+
+ /* Rooks & Queen */
+ b = (a[rook] | a[queen]) & MoveArray[rook][sq];
+ d = ~b & blocker;
+ while (b)
+ {
+ t = leadz (b);
+ if (!(c[t] & d))
+ return (true);
+ CLEARBIT (b, t);
+ }
+ return (false);
+}
+
+extern const short raybeg[];
+extern const short rayend[];
+
+void GenAtaks (void)
+/*************************************************************************
+ *
+ * To generate the attack table.
+ * Ataks[side][0] holds the total attack tables.
+ * Ataks[side][pawn] holds the BitBoard of squares attacked by all pawns.
+ *
+ *************************************************************************/
+{
+ int side;
+ int sq;
+ register BitBoard *a, b, *t, *a0;
+
+ memset (Ataks, 0, sizeof (Ataks));
+ for (side = white; side <= black; side++)
+ {
+ a = board.b[side];
+
+ /* Knight */
+ t = &Ataks[side][knight];
+ b = a[knight];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ *t |= MoveArray[knight][sq];
+ }
+
+ /* Bishops */
+ t = &Ataks[side][bishop];
+ b = a[bishop];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ *t |= BishopAttack(sq);
+ }
+
+ /* Rooks */
+ t = &Ataks[side][rook];
+ b = a[rook];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ *t |= RookAttack(sq);
+ }
+
+ /* Queen */
+ t = &Ataks[side][queen];
+ b = a[queen];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ *t |= QueenAttack(sq);
+ }
+
+ /* King */
+ t = &Ataks[side][king];
+ b = a[king];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ *t |= MoveArray[king][sq];
+ }
+
+ /* pawns */
+ t = &Ataks[side][pawn];
+ if (side == white)
+ {
+ b = board.b[white][pawn] & ~FileBit[0];
+ *t |= (b >> 7);
+ b = board.b[white][pawn] & ~FileBit[7];
+ *t |= (b >> 9);
+ }
+ else
+ {
+ b = board.b[black][pawn] & ~FileBit[0];
+ *t |= (b << 9);
+ b = board.b[black][pawn] & ~FileBit[7];
+ *t |= (b << 7);
+ }
+ a0 = Ataks[side];
+ a0[0] = a0[pawn] | a0[knight] | a0[bishop] | a0[rook] |
+ a0[queen] | a0[king];
+ }
+}
+
+
+BitBoard AttackTo (int sq, int side)
+/***************************************************************************
+ *
+ * Generate a bitboard of all squares with pieces belonging to side
+ * which attack sq.
+ *
+ ***************************************************************************/
+{
+ register BitBoard *a, b, *c, e, blocker;
+ int t;
+
+ a = board.b[side];
+
+ /* Knights */
+ e = (a[knight] & MoveArray[knight][sq]);
+
+ /* Kings */
+ e |= (a[king] & MoveArray[king][sq]);
+
+ /* Pawns */
+ e |= (a[pawn] & MoveArray[ptype[1^side]][sq]);
+
+ c = FromToRay[sq];
+ blocker = board.blocker;
+
+ /* Bishops & Queen */
+ b = (a[bishop] | a[queen]) & MoveArray[bishop][sq];
+ while (b)
+ {
+ t = leadz (b);
+ CLEARBIT (b, t);
+ if (!(c[t] & blocker & NotBitPosArray[t]))
+ e |= BitPosArray[t];
+ }
+
+ /* Rooks & Queen */
+ b = (a[rook] | a[queen]) & MoveArray[rook][sq];
+ while (b)
+ {
+ t = leadz (b);
+ CLEARBIT (b, t);
+ if (!(c[t] & blocker & NotBitPosArray[t]))
+ e |= BitPosArray[t];
+ }
+
+ return (e);
+}
+
+
+BitBoard AttackXTo (int sq, int side)
+/***************************************************************************
+ *
+ * Generate a bitboard of all squares with pieces belonging to side
+ * which attack sq. This routine is slightly different from AttackTo
+ * as it includes X-ray attacks as well and these can go through the
+ * opponents pieces as well (e.g. a white R will attack the squares
+ * beyond the black R).
+ *
+ ***************************************************************************/
+{
+ register BitBoard *a, b, *c, *d, e, blocker;
+ int t;
+
+ a = board.b[side];
+ d = board.b[1^side];
+
+ /* Knights */
+ e = (a[knight] & MoveArray[knight][sq]);
+
+ /* Kings */
+ e |= (a[king] & MoveArray[king][sq]);
+
+ c = FromToRay[sq];
+
+ /* Bishops & Queen & Pawns */
+ b = (a[pawn] & MoveArray[ptype[1^side]][sq]);
+ blocker = board.blocker;
+ blocker &= ~(a[bishop] | a[queen] | d[bishop] | d[queen] | b);
+ b |= (a[bishop] | a[queen]) & MoveArray[bishop][sq];
+ while (b)
+ {
+ t = leadz (b);
+ CLEARBIT (b, t);
+ if (!(c[t] & blocker & NotBitPosArray[t]))
+ e |= BitPosArray[t];
+ }
+
+ /* Rooks & Queen */
+ b = (a[rook] | a[queen]) & MoveArray[rook][sq];
+ blocker = board.blocker;
+ blocker &= ~(a[rook] | a[queen] | d[rook] | d[queen]);
+ while (b)
+ {
+ t = leadz (b);
+ CLEARBIT (b, t);
+ if (!(c[t] & blocker & NotBitPosArray[t]))
+ e |= BitPosArray[t];
+ }
+
+ return (e);
+}
+
+
+BitBoard AttackFrom (int sq, int piece, int side)
+/***************************************************************************
+ *
+ * Generate a bitboard of all squares attacked by a piece on sq.
+ *
+ ***************************************************************************/
+{
+ switch (piece)
+ {
+ case pawn :
+ return (MoveArray[ptype[side]][sq]);
+ case knight :
+ return (MoveArray[knight][sq]);
+ case bishop :
+ return (BishopAttack(sq));
+ case rook :
+ return (RookAttack(sq));
+ case queen :
+ return (QueenAttack(sq));
+ case king :
+ return (MoveArray[king][sq]);
+ }
+ return (0);
+}
+
+
+BitBoard AttackXFrom (int sq, int side)
+/***************************************************************************
+ *
+ * Generate a bitboard of all squares attacked by a piece on sq. This
+ * routine is different from AttackFrom in that it includes Xray attacks.
+ * Caveat: This routine does not take into account xrays through pawns.
+ *
+ ***************************************************************************/
+{
+ register BitBoard *a, b, c, blocker;
+ int piece, dir, blocksq;
+
+ a = board.b[side];
+ piece = cboard[sq];
+ blocker = board.blocker;
+ b = 0;
+ switch (piece)
+ {
+ case pawn :
+ b = MoveArray[ptype[side]][sq];
+ break;
+ case knight :
+ b = MoveArray[knight][sq];
+ break;
+ case bishop : /* falls through as queens move diagnonally */
+ case queen :
+ blocker &= ~(a[bishop] | a[queen]);
+ for (dir = raybeg[bishop]; dir < rayend[bishop]; dir++)
+ {
+ c = Ray[sq][dir] & blocker;
+ if (c == NULLBITBOARD)
+ c = Ray[sq][dir];
+ else
+ {
+ blocksq = (BitPosArray[sq] > c ? leadz (c) : trailz (c));
+ c = FromToRay[sq][blocksq];
+ }
+ b |= c;
+ }
+ if (piece == bishop) /* Queen falls through as they move like rooks */
+ break;
+ blocker = board.blocker;
+ case rook :
+ blocker &= ~(a[rook] | a[queen]);
+ for (dir = raybeg[rook]; dir < rayend[rook]; dir++)
+ {
+ c = Ray[sq][dir] & blocker;
+ if (c == NULLBITBOARD)
+ c = Ray[sq][dir];
+ else
+ {
+ blocksq = (BitPosArray[sq] > c ? leadz (c) : trailz (c));
+ c = FromToRay[sq][blocksq];
+ }
+ b |= c;
+ }
+ break;
+ case king :
+ b = MoveArray[king][sq];
+ break;
+ }
+ return (b);
+}
+
+
+int PinnedOnKing (int sq, int side)
+/***************************************************************************
+ *
+ * Determine if the piece on sq is pinned against the King.
+ * Side is the color of the piece.
+ * Caveat: PinnedOnKing should only be called by GenCheckEscapes().
+ * The more generic FindPins() function should be used for evaluating
+ * pins against other pieces.
+ *
+ ***************************************************************************/
+{
+ int xside;
+ int KingSq, dir, sq1;
+ BitBoard b, blocker;
+
+ KingSq = board.king[side];
+ if ((dir = directions[KingSq][sq]) == -1)
+ return (false);
+
+ xside = 1 ^ side;
+ blocker = board.blocker;
+
+ /* Path from piece to king is blocked, so no pin */
+ if (FromToRay[KingSq][sq] & NotBitPosArray[sq] & blocker)
+ return (false);
+ b = (Ray[KingSq][dir] ^ FromToRay[KingSq][sq]) & blocker;
+ if (b == NULLBITBOARD)
+ return (false);
+ sq1 = (sq > KingSq ? leadz (b) : trailz (b));
+
+ /* If diagonal */
+ if (dir <= 3 &&
+ BitPosArray[sq1] & (board.b[xside][queen] | board.b[xside][bishop]))
+ return (true);
+
+ /* Rank / file */
+ if (dir >= 4 &&
+ BitPosArray[sq1] & (board.b[xside][queen] | board.b[xside][rook]))
+ return (true);
+
+ return (false);
+}
+
+
+void FindPins (BitBoard *pin)
+/***************************************************************************
+ *
+ * This function creates a bitboard of all pieces which are pinned.
+ *
+ ***************************************************************************/
+{
+ int side, xside;
+ int sq, sq1;
+ BitBoard b, c, e, f, t, *p;
+
+ *pin = NULLBITBOARD;
+ t = board.friends[white] | board.friends[black];
+ for (side = white; side <= black; side++)
+ {
+ xside = 1^side;
+ p = board.b[xside];
+
+ /* Check if bishop is pinning anything */
+ e = p[rook] | p[queen] | p[king];
+ e |= (p[bishop] | p[knight]) & ~Ataks[xside][0];
+ b = board.b[side][bishop];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+
+ c = MoveArray[bishop][sq] & e;
+ while (c)
+ {
+ sq1 = leadz (c);
+ CLEARBIT (c, sq1);
+ f = t & NotBitPosArray[sq] & FromToRay[sq1][sq];
+ if ((board.friends[xside] & f) && nbits (f) == 1)
+ *pin |= f;
+ }
+ }
+
+ /* Check if rook is pinning anything */
+ e = p[queen] | p[king];
+ e |= (p[rook] | p[bishop] | p[knight]) & ~Ataks[xside][0];
+ b = board.b[side][rook];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+
+ c = MoveArray[rook][sq] & e;
+ while (c)
+ {
+ sq1 = leadz (c);
+ CLEARBIT (c, sq1);
+ f = t & NotBitPosArray[sq] & FromToRay[sq1][sq];
+ if ((board.friends[xside] & f) && nbits (f) == 1)
+ *pin |= f;
+ }
+ }
+
+ /* Check if queen is pinning anything */
+ e = board.b[xside][king];
+ e |= (p[queen] | p[rook] | p[bishop] | p[knight]) & ~Ataks[xside][0];
+ b = board.b[side][queen];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+
+ c = MoveArray[queen][sq] & e;
+ while (c)
+ {
+ sq1 = leadz (c);
+ CLEARBIT (c, sq1);
+ f = t & NotBitPosArray[sq] & FromToRay[sq1][sq];
+ if ((board.friends[xside] & f) && nbits (f) == 1)
+
+ *pin |= f;
+ }
+ }
+ }
+
+ return ;
+}
+
+
+int MateScan (int side)
+/***************************************************************************
+ *
+ * This routine scans the squares around the king to see if a Q + piece
+ * is attacking any of them. If none, return 0, else return 1.
+ * If the square is defended, there is no threat.
+ * Limitations: Assume only 1 Q present.
+ *
+ ***************************************************************************/
+{
+ int KingSq, QueenSq, sq;
+ int xside;
+ BitBoard b;
+
+ xside = 1 ^ side;
+
+ /* Opponent has no queen, forget it */
+ if (board.b[xside][queen] == 0)
+ return (0);
+
+ KingSq = board.king[side];
+ QueenSq = leadz (board.b[xside][queen]);
+ b = QueenAttack(QueenSq) & MoveArray[king][KingSq];
+ if (b == 0)
+ return (0);
+
+ while (b)
+ {
+ sq = leadz (b);
+ if (AttackTo (sq, side) == board.b[side][king] &&
+ AttackXTo (sq, xside) != board.b[xside][queen])
+ return (1);
+ CLEARBIT (b, sq);
+ }
+
+ return (0);
+}
diff --git a/src/chess_computer-activity/gnuchess/book.c b/src/chess_computer-activity/gnuchess/book.c
new file mode 100644
index 0000000..e43ad1e
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/book.c
@@ -0,0 +1,693 @@
+/* GNU Chess 5.0 - book.c - book code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+ lukas debian org
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "book.h"
+
+#define MAXMOVES 200
+#define MAXMATCH 100
+
+/*
+ * BookQuery() tries the following filenames in order to find
+ * a valid opening book. The array must be NULL-terminated.
+ */
+static char const * bookbin[] = {
+ "book.dat",
+ "/usr/share/games/gnuchess/book.dat",
+ "/usr/lib/games/gnuchess/book.dat",
+ NULL
+};
+
+static int bookcnt;
+static HashType posshash[MAXMOVES];
+
+/*
+ * This is the only authoritative variable telling us
+ * whether a book has been allocated or not. (Other
+ * parts may mess around with bookloaded.)
+ */
+static int book_allocated = 0;
+
+/*
+ * The last byte of magic_str should be the version
+ * number of the format, in case we have to change it.
+ *
+ * Format 0x01 had an index field which is now gone.
+ *
+ * Format 0x03 uses an additional size header, which
+ * comes directly after the magic string, and has the
+ * number of entries as a big-endian encoded uint32_t
+ * number.
+ */
+
+#define MAGIC_LENGTH 5
+
+static const char magic_str[] = "\x42\x23\x08\x15\x03";
+
+static int check_magic(FILE *f)
+{
+ char buf[MAGIC_LENGTH];
+ int r;
+
+ r = fread(&buf, 1, MAGIC_LENGTH, f);
+ return (r == MAGIC_LENGTH &&
+ memcmp(buf, magic_str, MAGIC_LENGTH) == 0);
+}
+
+static int write_magic(FILE *f)
+{
+ if (MAGIC_LENGTH != fwrite(&magic_str, 1, MAGIC_LENGTH, f)) {
+ return BOOK_EIO;
+ } else {
+ return BOOK_SUCCESS;
+ }
+}
+
+/* Write and read size information for the binary book */
+
+static int write_size(FILE *f, uint32_t size)
+{
+ unsigned char sizebuf[4];
+ int k;
+
+ for (k = 0; k < 4; k++) {
+ sizebuf[k] = (size >> ((3-k)*8)) & 0xff;
+ }
+ if (1 == fwrite(&sizebuf, sizeof(sizebuf), 1, f)) {
+ return BOOK_SUCCESS;
+ } else {
+ return BOOK_EIO;
+ }
+}
+
+/* Returns 0 if some read error occurs */
+
+static uint32_t read_size(FILE *f)
+{
+ unsigned char sizebuf[4];
+ uint32_t size = 0;
+ int k;
+
+ if (1 != fread(&sizebuf, sizeof(sizebuf), 1, f)) {
+ return 0;
+ }
+ for (k = 0; k < 4; k++) {
+ size = (size << 8) | sizebuf[k];
+ }
+ return size;
+}
+
+/*
+ * We now allocate memory for the book dynamically,
+ * according to the size field in the header of the binary
+ * book. However, during book building the following value
+ * is used.
+ */
+
+#define MAX_DIGEST_BITS 20
+
+static int digest_bits;
+
+#define DIGEST_SIZE (1UL << digest_bits)
+#define DIGEST_MASK (DIGEST_SIZE - 1)
+
+static struct hashtype {
+ uint16_t wins;
+ uint16_t losses;
+ uint16_t draws;
+ HashType key;
+} *bookpos;
+
+static inline int is_empty(uint32_t index)
+{
+ return
+ bookpos[index].key == 0 &&
+ bookpos[index].wins == 0 &&
+ bookpos[index].draws == 0 &&
+ bookpos[index].losses == 0;
+}
+
+/*
+ * Initial hash function, relies on the quality of the lower
+ * bits of the 64 bit hash function
+ */
+#define DIGEST_START(i,key) \
+ ((i) = (key) & DIGEST_MASK)
+
+/*
+ * See if there is already a matching entry
+ */
+#define DIGEST_MATCH(i,the_key) \
+ ((the_key) == bookpos[i].key)
+
+/*
+ * See if the entry is empty
+ */
+#define DIGEST_EMPTY(i) is_empty(i)
+
+/*
+ * Check for collision
+ */
+#define DIGEST_COLLISION(i,key) \
+ (!DIGEST_MATCH(i,key) && !DIGEST_EMPTY(i))
+
+/*
+ * The next macro is used in the case of hash collisions.
+ * We use double hashing with the higher bits of the key.
+ * In order to have the shift relatively prime to the hash
+ * size, we OR by 1.
+ */
+#define DIGEST_NEXT(i,key) \
+ ((i) = ((i) + (((key) >> digest_bits) | 1)) & DIGEST_MASK)
+
+
+/* Mainly for debugging purposes */
+static int bookhashcollisions = 0;
+
+/*
+ * This is considered to be the limit for the hash, I chose
+ * 95% because it is Monday... No, I am open for suggestions
+ * for the right value, I just don't know.
+ */
+#define DIGEST_LIMIT (0.95 * DIGEST_SIZE)
+
+/*
+ * This is the record as it will be written in the binary
+ * file in network byte order. HashType is uint64_t. To
+ * avoid endianness and padding issues, we do not read or
+ * write structs but put the values in an unsigned char array.
+ */
+
+static unsigned char buf[2+2+2+8];
+
+/* Offsets */
+static const int wins_off = 0;
+static const int losses_off = 2;
+static const int draws_off = 4;
+static const int key_off = 6;
+
+static void buf_to_book(void)
+{
+ HashType key;
+ uint32_t i;
+
+ key = ((uint64_t)buf[key_off] << 56)
+ | ((uint64_t)buf[key_off+1] << 48)
+ | ((uint64_t)buf[key_off+2] << 40)
+ | ((uint64_t)buf[key_off+3] << 32)
+ | ((uint64_t)buf[key_off+4] << 24)
+ | ((uint64_t)buf[key_off+5] << 16)
+ | ((uint64_t)buf[key_off+6] << 8)
+ | ((uint64_t)buf[key_off+7]);
+ /*
+ * This is an infinite loop if the hash is 100% full,
+ * but other parts should check that this does not happen.
+ */
+ for (DIGEST_START(i, key);
+ DIGEST_COLLISION(i, key);
+ DIGEST_NEXT(i, key))
+ /* Skip */
+ bookhashcollisions++;
+
+ bookpos[i].wins += (buf[wins_off] << 8) | buf[wins_off +1];
+ bookpos[i].draws += (buf[draws_off] << 8) | buf[draws_off +1];
+ bookpos[i].losses += (buf[losses_off] << 8) | buf[losses_off+1];
+ bookpos[i].key = key;
+}
+
+static void book_to_buf(uint32_t index)
+{
+ int k;
+
+ for (k=0; k<2; k++) {
+ buf[wins_off + k] = ((bookpos[index].wins) >> ((1-k)*8)) & 0xff;
+ buf[draws_off + k] = ((bookpos[index].draws) >> ((1-k)*8)) & 0xff;
+ buf[losses_off + k] = ((bookpos[index].losses) >> ((1-k)*8)) & 0xff;
+ }
+ for (k=0; k<8; k++) {
+ buf[key_off + k] = ((bookpos[index].key) >> ((7-k)*8)) & 0xff;
+ }
+}
+
+static int compare(const void *aa, const void *bb)
+{
+ const leaf *a = aa;
+ const leaf *b = bb;
+
+ if (b->score > a->score) return(1);
+ else if (b->score < a->score) return(-1);
+ else return(0);
+}
+
+/*
+ * Reads an existing binary book from f. The header must
+ * already be skipped, when you call this function. The
+ * variable digest_bits must be set to the correct value
+ * before calling this function. If any book was allocated
+ * before, it will be lost.
+ */
+static int read_book(FILE *f)
+{
+ if (book_allocated) {
+ free(bookpos);
+ book_allocated = 0;
+ }
+ bookpos = calloc(DIGEST_SIZE, sizeof(struct hashtype));
+ if (bookpos == NULL) {
+ return BOOK_ENOMEM;
+ }
+ book_allocated = 1;
+ bookcnt = 0;
+ bookhashcollisions = 0;
+ while ( 1 == fread(&buf, sizeof(buf), 1, f) ) {
+ buf_to_book();
+ bookcnt++;
+ }
+ return BOOK_SUCCESS;
+}
+
+/*
+ * Return values are defined in common.h
+ */
+
+int BookBuilderOpen(void)
+{
+ FILE *rfp, *wfp;
+ int res;
+
+ if ((rfp = fopen(BOOKRUN,"rb")) != NULL) {
+ printf("Opened existing book!\n");
+ if (!check_magic(rfp)) {
+ fprintf(stderr,
+ "File %s does not conform to the current format.\n"
+ "Consider rebuilding your book.\n",
+ BOOKRUN);
+ return BOOK_EFORMAT;
+ }
+ /*
+ * We have to read the size header, but in book building we
+ * use the maximum-sized hash table, so we discard the value.
+ */
+ digest_bits = MAX_DIGEST_BITS;
+ read_size(rfp);
+ res = read_book(rfp);
+ fclose(rfp);
+ if (res != BOOK_SUCCESS) {
+ fclose(rfp);
+ return res;
+ }
+ printf("Read %d book positions\n", bookcnt);
+ printf("Got %d hash collisions\n", bookhashcollisions);
+ } else {
+ wfp = fopen(BOOKRUN,"w+b");
+ if (wfp == NULL) {
+ fprintf(stderr, "Could not create %s file: %s\n",
+ BOOKRUN, strerror(errno));
+ return BOOK_EIO;
+ }
+ if (write_magic(wfp) != BOOK_SUCCESS) {
+ fprintf(stderr, "Could not write to %s: %s\n",
+ BOOKRUN, strerror(errno));
+ return BOOK_EIO;
+ }
+ if (fclose(wfp) != 0) {
+ fprintf(stderr, "Could not write to %s: %s\n",
+ BOOKRUN, strerror(errno));
+ return BOOK_EIO;
+ }
+ printf("Created new book %s!\n", BOOKRUN);
+ rfp = fopen(BOOKRUN, "rb");
+ if (rfp == NULL) {
+ fprintf(stderr, "Could not open %s for reading: %s\n",
+ BOOKRUN, strerror(errno));
+ return BOOK_EIO;
+ }
+ digest_bits = MAX_DIGEST_BITS;
+ /* We use read_book() here only to allocate memory */
+ if (read_book(wfp) == BOOK_ENOMEM) {
+ return BOOK_ENOMEM;
+ }
+ }
+ return BOOK_SUCCESS;
+}
+
+/*
+ * Store the position and results of last search
+ * if and only if in the first 10 moves of the game.
+ * This routine is called after the computer makes its
+ * most recent move. Lastly, after the 10th move, on
+ * the 11th move, store the data out to the running file.
+ */
+/*
+ * NOTE: Before you build a book, you have to call
+ * BookBuilderOpen() now, after building it BookBuilderClose()
+ * in order to actually write the book to disk.
+ */
+
+int BookBuilder(short result, uint8_t side)
+{
+ uint32_t i;
+
+ /* Only first BOOKDEPTH moves */
+ if (GameCnt > BOOKDEPTH)
+ return BOOK_EMIDGAME;
+ CalcHashKey();
+ for (DIGEST_START(i, HashKey);
+ ;
+ DIGEST_NEXT(i, HashKey)) {
+ if (DIGEST_MATCH(i, HashKey)) {
+ existpos++;
+ break;
+ } else if (DIGEST_EMPTY(i)) {
+ if (bookcnt > DIGEST_LIMIT)
+ return BOOK_EFULL;
+ bookpos[i].key = HashKey;
+ newpos++;
+ bookcnt++;
+ break;
+ } else {
+ bookhashcollisions++;
+ }
+ }
+ if (side == white) {
+ if (result == R_WHITE_WINS)
+ bookpos[i].wins++;
+ else if (result == R_BLACK_WINS)
+ bookpos[i].losses++;
+ else if (result == R_DRAW)
+ bookpos[i].draws++;
+ } else {
+ if (result == R_WHITE_WINS)
+ bookpos[i].losses++;
+ else if (result == R_BLACK_WINS)
+ bookpos[i].wins++;
+ else if (result == R_DRAW)
+ bookpos[i].draws++;
+ }
+ return BOOK_SUCCESS;
+}
+
+int BookBuilderClose(void)
+{
+ /*
+ * IMHO the following part needs no temporary file.
+ * If two gnuchess invocations try to write the same
+ * file at the same time, this goes wrong anyway.
+ * Please correct me if I am wrong. If you generate
+ * a temporary file, try to generate it in some writable
+ * directory.
+ */
+ FILE *wfp;
+ unsigned int i;
+ int errcode = BOOK_SUCCESS;
+
+ wfp = fopen(BOOKRUN, "wb");
+ if (wfp == NULL) {
+ errcode = BOOK_EIO;
+ goto bailout_noclose;
+ }
+ if (write_magic(wfp) != BOOK_SUCCESS) {
+ errcode = BOOK_EIO;
+ goto bailout;
+ }
+ if (write_size(wfp, bookcnt) != BOOK_SUCCESS) {
+ errcode = BOOK_EIO;
+ goto bailout;
+ }
+ for (i = 0; i < DIGEST_SIZE; i++) {
+ if (!is_empty(i)) {
+ book_to_buf(i);
+ if (1 != fwrite(&buf, sizeof(buf), 1, wfp)) {
+ errcode = BOOK_EIO;
+ goto bailout;
+ }
+ }
+ }
+ printf("Got %d hash collisions\n", bookhashcollisions);
+
+ bailout:
+ if (fclose(wfp) != 0) {
+ errcode = BOOK_EIO;
+ }
+
+ bailout_noclose:
+ free(bookpos);
+ book_allocated = 0;
+
+ /* Let BookQuery allocate again */
+ bookloaded = 0;
+
+ return errcode;
+}
+
+/*
+ * Return values are defined in common.h
+ * NOTE: This function now returns BOOK_SUCCESS on
+ * success, which is 0. So all the possible callers
+ * should adjust to this. (At present it is only called
+ * in iterate.c.) It used to return 1 on success before.
+ */
+
+int BookQuery(int BKquery)
+{
+ /*
+ * BKquery denotes format; 0 text, 1 engine
+ * In general out put is engine compliant, lines start with a blank
+ * and end with emtpy line
+ */
+ int i,j,k,icnt = 0, mcnt, found, tot, maxdistribution;
+ int matches[MAXMATCH] ;
+ leaf m[MAXMOVES];
+ leaf pref[MAXMOVES];
+ struct {
+ uint16_t wins;
+ uint16_t losses;
+ uint16_t draws;
+ } r[MAXMOVES];
+ FILE *rfp = NULL;
+ leaf *p;
+ short side,xside,temp;
+ uint32_t booksize;
+ int res;
+
+ if (bookloaded && !book_allocated) {
+ /* Something failed during loading the book */
+ return BOOK_ENOBOOK;
+ }
+ if (!bookloaded) {
+ char const * const *booktry;
+
+ bookloaded = 1;
+ for (booktry = bookbin; *booktry ; booktry++) {
+ if (!(flags & XBOARD)) {
+ fprintf(ofp, "Looking for opening book in %s...\n", *booktry);
+ }
+ rfp = fopen(*booktry, "rb");
+ /* XXX: Any further error analysis here? -- Lukas */
+ if (rfp == NULL) continue;
+ if (!(flags & XBOARD))
+ fprintf(ofp,"Read opening book (%s)...\n", *booktry);
+ if (!check_magic(rfp)) {
+ fprintf(stderr,
+ " File %s does not conform to the current format.\n"
+ " Consider rebuilding it.\n\n",
+ *booktry);
+ fclose(rfp);
+ rfp = NULL;
+ } else break; /* Success, stop search */
+ }
+ if (rfp == NULL) {
+ /* If appropriate print error */
+ if (!(flags & XBOARD) || BKquery == 1)
+ fprintf(ofp," No book found.\n\n");
+ return BOOK_ENOBOOK;
+ }
+ if (!(flags & XBOARD)) {
+ fprintf(ofp, "Loading book from %s.\n", *booktry);
+ }
+ /*
+ * The factor 1.06 is the minimum additional amount of
+ * free space in the hash
+ */
+ booksize = read_size(rfp) * 1.06;
+ for (digest_bits = 1; booksize; booksize >>= 1) {
+ digest_bits++;
+ }
+ res = read_book(rfp);
+ if (res != BOOK_SUCCESS) {
+ return res;
+ }
+ if (!(flags & XBOARD))
+ fprintf(ofp,"%d hash collisions... ", bookhashcollisions);
+ }
+
+ mcnt = -1;
+ side = board.side;
+ xside = 1^side;
+ TreePtr[2] = TreePtr[1];
+ GenMoves(1);
+ FilterIllegalMoves (1);
+ for (p = TreePtr[1]; p < TreePtr[2]; p++) {
+ MakeMove(side, &p->move);
+ m[icnt].move = p->move;
+ posshash[icnt] = HashKey;
+ icnt++;
+ UnmakeMove(xside,&p->move);
+ }
+ for (i = 0; i < icnt; i++) {
+ for (DIGEST_START(j,posshash[i]);
+ !DIGEST_EMPTY(j);
+ DIGEST_NEXT(j, posshash[i])) {
+ if (DIGEST_MATCH(j, posshash[i])) {
+ found = 0;
+ for (k = 0; k < mcnt; k++)
+ if (matches[k] == i) {
+ found = 1;
+ break;
+ }
+ /* Position must have at least some wins to be played by book */
+ if (!found) {
+ matches[++mcnt] = i;
+ pref[mcnt].move = m[matches[mcnt]].move;
+ r[i].losses = bookpos[j].losses;
+ r[i].wins = bookpos[j].wins;
+ r[i].draws = bookpos[j].draws;
+
+ /* by percent score starting from this book position */
+
+ pref[mcnt].score = m[i].score =
+ 100*(r[i].wins+(r[i].draws/2))/
+ (MAX(r[i].wins+r[i].losses+r[i].draws,1)) + r[i].wins/2;
+
+ }
+ if (mcnt >= MAXMATCH) {
+ fprintf(ofp," Too many matches in book.\n\n");
+ goto fini;
+ }
+ break; /* If we found a match, the following positions can not match */
+ }
+ }
+ }
+
+fini:
+ if (!(flags & XBOARD) || BKquery == 1)
+ {
+ fprintf(ofp," Opening database: %d book positions.\n",bookcnt);
+ if (mcnt+1 == 0) {
+ fprintf(ofp," In this position, there is no book move.\n\n");
+ } else if (mcnt+1 == 1) {
+ fprintf(ofp," In this position, there is one book move:\n");
+ } else {
+ fprintf(ofp," In this position, there are %d book moves:\n", mcnt+1);
+ }
+ }
+ /* No book moves */
+ if (mcnt == -1) {
+ return BOOK_ENOMOVES;
+ }
+ k = 0;
+ if (mcnt+1) {
+ if ( !(flags & XBOARD) || BKquery == 1 ) {
+ for (i = 0; i <= mcnt; i++) {
+ if (!(flags & XBOARD) || BKquery == 1 ) {
+ SANMove(m[matches[i]].move,1);
+ tot = r[matches[i]].wins+r[matches[i]].draws+r[matches[i]].losses;
+ fprintf(ofp," %s(%2.0f/%d/%d/%d) ",SANmv,
+ 100.0*(r[matches[i]].wins+(r[matches[i]].draws/2.0))/tot,
+ r[matches[i]].wins,
+ r[matches[i]].losses,
+ r[matches[i]].draws);
+ if ((i+1) % 4 == 0) fputc('\n',ofp);
+ }
+ }
+ if (!(flags & XBOARD) || BKquery == 1 )
+ if (i % 4 != 0) fprintf(ofp," \n \n");
+ }
+ if (bookmode == BOOKRAND) {
+ k = rand();
+ k = k % (mcnt+1);
+ RootPV = m[matches[k]].move;
+ if (!(flags & XBOARD)) {
+ printf("\n(Random picked move #%d %s%s from above list)\n",k,
+ algbr[FROMSQ(RootPV)],algbr[TOSQ(RootPV)]);
+ tot = r[matches[k]].wins+r[matches[k]].draws+r[matches[k]].losses;
+ if (tot != 0)
+ printf("B p=%2.0f\n",
+ 100.0*(r[matches[k]].wins+r[matches[k]].draws)/tot);
+ else
+ printf("p=NO EXPERIENCES\n");
+ }
+ } else if (bookmode == BOOKBEST) {
+ qsort(&pref,mcnt+1,sizeof(leaf),compare);
+ RootPV = pref[0].move;
+ } else if (bookmode == BOOKWORST) {
+ qsort(&pref,mcnt+1,sizeof(leaf),compare);
+ RootPV = pref[mcnt].move;
+ } else if (bookmode == BOOKPREFER) {
+ qsort(&pref,mcnt+1,sizeof(leaf),compare);
+ for (i = 0; i <= mcnt; i++) {
+ if (!(flags & XBOARD) || BKquery == 1) {
+ SANMove(pref[i].move,1);
+ printf(" %s(%d) ",SANmv,pref[i].score);
+ }
+ m[i].move = pref[i].move;
+ if (!(flags & XBOARD) || BKquery == 1)
+ if ((i+1) % 8 == 0) fputc('\n',ofp);
+ }
+ if (!(flags & XBOARD) || BKquery == 1)
+ if (i % 8 != 0) fprintf(ofp," \n \n");
+ temp = (bookfirstlast > mcnt+1 ? mcnt+1 : bookfirstlast);
+ /* Choose from the top preferred moves based on distribution */
+ maxdistribution = 0;
+ for (i = 0; i < temp; i++)
+ maxdistribution += pref[i].score;
+ /* Do not play moves that have only losses! */
+ if (maxdistribution == 0)
+ return BOOK_ENOMOVES;
+ k = rand() % maxdistribution;
+ maxdistribution = 0;
+ for (i = 0; i < temp; i++) {
+ maxdistribution += pref[i].score;
+ if (k >= maxdistribution - pref[i].score &&
+ k < maxdistribution)
+ {
+ k = i;
+ RootPV = m[k].move;
+ break;
+ }
+ }
+ }
+ }
+ return BOOK_SUCCESS;
+}
diff --git a/src/chess_computer-activity/gnuchess/book.h b/src/chess_computer-activity/gnuchess/book.h
new file mode 100644
index 0000000..82d9918
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/book.h
@@ -0,0 +1,35 @@
+/* GNU Chess 5.0 - book.h - book symbolic definitions
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+#define BOOKSRC "book.src"
+
+/* The book which BookBuilder() uses */
+#define BOOKRUN "book.dat"
+
+#define R_WHITE_WINS 1
+#define R_BLACK_WINS 2
+#define R_DRAW 3
+#define R_NORESULT 4
+#define BOOKDEPTH 20 /* We gobble this many moves from each PGN book game */
diff --git a/src/chess_computer-activity/gnuchess/cmd.c b/src/chess_computer-activity/gnuchess/cmd.c
new file mode 100644
index 0000000..843bb04
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/cmd.c
@@ -0,0 +1,995 @@
+/* GNU Chess 5.0 - cmd.c - command parser
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "version.h"
+#include "common.h"
+#include "eval.h"
+
+static char logfile[MAXSTR];
+static char gamefile[MAXSTR];
+
+/*
+ * Splitting input is actually not neccessary, but we find
+ * tokens separated by whitespace and put pointers on them.
+ * How many do we need? We just take 3 for now. Check if the
+ * fact that tokens are not 0-terminated but whitespace-terminated
+ * generates bugs. (Already killed one bug in move.c)
+ * We also kill trailing whitespace. (The trailing '\n' might
+ * be really annoying otherwise.)
+ */
+
+#define TOKENS 3
+
+static char *token[TOKENS];
+char *endptr;
+
+static void split_input(void)
+{
+ /* r points to the last non-space character */
+ char *s, *r;
+ int k;
+
+ for (k = 0, s = r = inputstr; k < TOKENS; ++k) {
+ /* Skip leading whitespace */
+ while (isspace(*s)) s++;
+ token[k] = s;
+ /* Skip token */
+ while (*s && !isspace(*s)) r = s++;
+ }
+ while (*s) {
+ while (isspace(*s)) s++;
+ while (*s && !isspace(*s)) r = s++;
+ }
+ r[1] = '\0';
+}
+
+/*
+ * Compares two tokens, returns 1 on equality. Tokens
+ * are separated by whitespace.
+ */
+static int tokeneq(const char *s, const char *t)
+{
+ while (*s && *t && !isspace(*s) && !isspace(*t)) {
+ if (*s++ != *t++) return 0;
+ }
+ return (!*s || isspace(*s)) && (!*t || isspace(*t));
+}
+
+void cmd_accepted(void) {}
+
+void cmd_activate(void)
+{
+ CLEAR (flags, TIMEOUT);
+ CLEAR (flags, ENDED);
+}
+
+void cmd_analyze(void)
+{
+ /*
+ * "analyze" mode is similar to force, hard and post together
+ * in that it produces a text output like post, but must
+ * think indefinitely like ponder.
+ *
+ * Some additional output is expected in command ".\n" but if ignored
+ * this should not be sent any more
+ */
+
+/* TODO correct output, add fail high low */
+
+ if (!(flags & ANALYZE)){
+ preanalyze_flags=flags; /* save these flags for exit */
+ SET (flags, ANALYZE);
+ cmd_post();
+ cmd_force();
+ cmd_hard();
+ }
+}
+
+void cmd_bk(void)
+{
+ /* Print moves from Open Book for Xboard/WinBoard */
+ /* Lines must start with " " and end with blank line */
+ /* No need to test for xboard as it is generally useful */
+ BookQuery(1);
+ printf("\n"); /* Blank line */
+ fflush(stdout);
+}
+
+void cmd_black(void)
+{
+ /*
+ * No longer used by Xboard but requested as a feature
+ */
+
+ NewPosition(); /* Reset some flags and settings */
+ CLEAR ( flags, THINK);
+ CLEAR ( flags, MANUAL);
+ CLEAR (flags, TIMEOUT);
+ computer = white;
+ if ( board.side == white ) {
+ board.side = black;
+ board.ep = -1;
+ }
+}
+
+void cmd_book(void)
+{
+ if (tokeneq(token[1], "add")) {
+ if (access(token[2], F_OK) < 0) {
+ printf("The syntax to add a new book is:\n\n\tbook add file.pgn\n");
+ } else {
+ BookPGNReadFromFile (token[2]);
+ }
+ } else if (tokeneq (token[1], "on") || tokeneq(token[1], "prefer")) {
+ bookmode = BOOKPREFER;
+ printf("book now on.\n");
+ } else if (tokeneq (token[1], "off")) {
+ bookmode = BOOKOFF;
+ printf("book now off.\n");
+ } else if (tokeneq (token[1], "best")) {
+ bookmode = BOOKBEST;
+ printf("book now best.\n");
+ } else if (tokeneq (token[1], "worst")) {
+ bookmode = BOOKWORST;
+ printf("book now worst.\n");
+ } else if (tokeneq (token[1], "random")) {
+ bookmode = BOOKRAND;
+ printf("book now random.\n");
+ }
+}
+
+/* Our opponent is a computer */
+void cmd_computer(void) {}
+
+void cmd_depth(void)
+{
+ SearchDepth = atoi (token[1]);
+ printf("Search to a depth of %d\n",SearchDepth);
+}
+
+/* Ignore draw offers */
+void cmd_draw(void) {}
+
+void cmd_easy(void) { CLEAR (flags, HARD); }
+
+/* Predecessor to setboard */
+void cmd_edit(void)
+{
+ if ( flags & XBOARD ) {
+ printf("tellusererror command 'edit' not implemented\n");
+ fflush(stdout);
+ }
+}
+
+void cmd_epd(void)
+{
+ ParseEPD (token[1]);
+ NewPosition();
+ ShowBoard();
+ printf ("\n%s : Best move = %s\n", id, solution);
+}
+
+void cmd_exit(void)
+{
+ /*
+ * "exit" is a synonym for quit except in engine mode
+ * when it means leave analyze mode
+ */
+
+ if ( flags & ANALYZE ){
+ flags = preanalyze_flags ; /* this implicitly clears ANALYZE flag */
+ } else {
+ cmd_quit();
+ }
+
+
+}
+
+void cmd_force(void) { SET (flags, MANUAL); }
+
+void cmd_go(void)
+{
+ SET (flags, THINK);
+ CLEAR (flags, MANUAL);
+ CLEAR (flags, TIMEOUT);
+ CLEAR (flags, ENDED);
+ computer = board.side;
+}
+
+void cmd_hard(void) { SET (flags, HARD); }
+
+void cmd_hash(void)
+{
+ if (tokeneq (token[1], "off"))
+ CLEAR (flags, USEHASH);
+ else if (tokeneq (token[1], "on"))
+ SET (flags, USEHASH);
+ printf ("Hashing %s\n", flags & USEHASH ? "on" : "off");
+}
+
+void cmd_hashsize(void)
+{
+ if (token[1][0] == 0) {
+ printf("Current HashSize is %d slots\n", HashSize);
+ } else {
+ int i;
+ /* i = atoi (token[1]); */
+ errno = 0;
+ i = strtol (token[1], &endptr, 10);
+ if ( errno != 0 || *endptr != '\0' ){
+ printf("Hashsize out of Range or Invalid\n");
+ }
+ else {
+ CalcHashSize(i);
+ InitHashTable ();
+ }
+ }
+}
+
+/* Give a possible move for the player to play */
+void cmd_hint(void)
+{
+ if ( flags & ENDED ){
+ printf("The game is over.\n");
+ } else {
+ int HintMove;
+ HintMove = TreePtr[1]->move; /* Pick first move in tree */
+ if (IsLegalMove(HintMove)){
+ GenMoves(1);
+ SANMove(TreePtr[1]->move,1);
+ printf("Hint: %s\n", SANmv);
+ } else {
+ printf("No hint available at this time\n");
+ }
+ }
+ fflush(stdout);
+}
+
+void cmd_level(void)
+{
+ SearchDepth = 0;
+ sscanf (token[1], "%d %f %d", &TCMove, &TCTime, &TCinc);
+ if (TCMove == 0) {
+ TCMove = 35 /* MIN((5*(GameCnt+1)/2)+1,60) */;
+ printf("TCMove = %d\n",TCMove);
+ suddendeath = 1;
+ } else
+ suddendeath = 0;
+ if (TCTime == 0) {
+ SET (flags, TIMECTL);
+ SearchTime = TCinc / 2.0f ;
+ printf("Fischer increment of %d seconds\n",TCinc);
+ } else {
+ SET (flags, TIMECTL);
+ MoveLimit[white] = MoveLimit[black] = TCMove - (GameCnt+1)/2;
+ TimeLimit[white] = TimeLimit[black] = TCTime * 60;
+ if (!(flags & XBOARD)) {
+ printf ("Time Control: %d moves in %.2f secs\n",
+ MoveLimit[white], TimeLimit[white]);
+ printf("Fischer increment of %d seconds\n",TCinc);
+ }
+ }
+}
+
+void cmd_list(void)
+{
+ if (token[1][0] == '?') {
+ printf("name - list known players alphabetically\n");
+ printf("score - list by GNU best result first \n");
+ printf("reverse - list by GNU worst result first\n");
+ } else {
+ if (token[1][0] == '\0') DBListPlayer("rscore");
+ else DBListPlayer(token[1]);
+ }
+}
+
+void cmd_load(void)
+{
+ LoadEPD (token[1]);
+ if (!ValidateBoard()) {
+ SET (flags, ENDED);
+ printf ("Board is wrong!\n");
+ }
+}
+
+void cmd_manual(void) { SET (flags, MANUAL); }
+
+/* Move now, not applicable */
+void cmd_movenow(void) {}
+
+/*
+ * TODO: Add a logpath variable or macro, not always dump into current
+ * dir. Again, how does one handle paths portably across Unix/Windows?
+ * -- Lukas
+ */
+void cmd_name(void)
+{
+ int suffix = 0;
+
+ /* name[sizeof name - 1] should always be 0 */
+ strncpy(name, token[1], sizeof name - 1);
+ for (suffix = 0; suffix < 1000; suffix++) {
+ sprintf(logfile,"log.%03d",suffix);
+ sprintf(gamefile,"game.%03d",suffix);
+ /*
+ * There is an obvious race condition here but who cares, we just
+ * bail out in case of failure... --Lukas
+ */
+ if (access(logfile,F_OK) < 0) {
+ ofp = fopen(logfile,"w");
+ if (ofp == NULL) {
+ ofp = stdout;
+ fprintf(stderr, "Failed to open %s for writing: %s\n",
+ logfile, strerror(errno));
+ }
+ return;
+ }
+ }
+ fprintf(stderr, "Could not create logfile, all slots occupied.\n");
+ fprintf(stderr, "You may consider deleting or renaming your existing logfiles.\n");
+}
+
+void cmd_new(void)
+{
+ InitVars ();
+ NewPosition ();
+ /* Protocol specification for ANALYZE says "new" does not end analysis */
+ if (!(flags & ANALYZE))
+ CLEAR (flags, MANUAL);
+ CLEAR (flags, THINK);
+ myrating = opprating = 0;
+}
+
+void cmd_nopost(void) { CLEAR (flags, POST); }
+
+void cmd_null(void)
+{
+ if (tokeneq (token[1], "off"))
+ CLEAR (flags, USENULL);
+ else if (tokeneq (token[1], "on"))
+ SET (flags, USENULL);
+ printf ("Null moves %s\n", flags & USENULL ? "on" : "off");
+}
+
+void cmd_otim(void) {}
+
+void cmd_pgnload(void) { PGNReadFromFile (token[1]); }
+
+/*
+ * XXX - Filenames with spaces will break here,
+ * do we want to support them? I vote for "no"
+ * - Lukas
+ */
+void cmd_pgnsave(void)
+{
+ if ( strlen(token[1]) > 0 )
+ PGNSaveToFile (token[1], "");
+ else
+ printf("Invalid filename.\n");
+}
+
+void cmd_ping(void)
+{
+ /* If ping is received when we are on move, we are supposed to
+ reply only after moving. In this version of GNU Chess, we
+ never read commands while we are on move, so we don't have to
+ worry about that here. */
+ printf("pong %s\n", token[1]);
+ fflush(stdout);
+}
+
+void cmd_post(void) { SET (flags, POST); }
+
+void cmd_protover(void)
+{
+ if (flags & XBOARD) {
+ /* Note: change this if "draw" command is added, etc. */
+ printf("feature setboard=1 analyze=1 ping=1 draw=0 sigint=0"
+ " variants=\"normal\" myname=\"%s %s\" done=1\n",
+ PROGRAM, VERSION);
+ fflush(stdout);
+ }
+}
+
+void cmd_quit(void) { SET (flags, QUIT); }
+
+void cmd_random(void) {}
+
+void cmd_rating(void)
+{
+ myrating = atoi(token[1]);
+ opprating = atoi(token[2]);
+ fprintf(ofp,"my rating = %d, opponent rating = %d\n",myrating,opprating);
+ /* Change randomness of book based on opponent rating. */
+ /* Basically we play narrower book the higher the opponent */
+ if (opprating >= 1700) bookfirstlast = 2;
+ else if (opprating >= 1700) bookfirstlast = 2;
+ else bookfirstlast = 2;
+}
+
+void cmd_rejected(void) {}
+
+void cmd_remove(void)
+{
+ if (GameCnt >= 0) {
+ CLEAR (flags, ENDED);
+ CLEAR (flags, TIMEOUT);
+ UnmakeMove (board.side, &Game[GameCnt].move);
+ if (GameCnt >= 0) {
+ UnmakeMove (board.side, &Game[GameCnt].move);
+ if (!(flags & XBOARD))
+ ShowBoard ();
+ }
+ PGNSaveToFile ("game.log","");
+ } else
+ printf ("No moves to undo! \n");
+}
+
+void cmd_result(void)
+{
+ if (ofp != stdout) {
+ fprintf(ofp, "result: %s\n",token[1]);
+ fclose(ofp);
+ ofp = stdout;
+ printf("Save to %s\n",gamefile);
+ PGNSaveToFile (gamefile, token[1]);
+ DBUpdatePlayer (name, token[1]);
+ }
+}
+
+void cmd_save(void)
+{
+ if ( strlen(token[1]) > 0 )
+ SaveEPD (token[1]);
+ else
+ printf("Invalid filename.\n");
+}
+
+void cmd_setboard(void)
+{
+ /* setboard uses FEN, not EPD, but ParseEPD will accept FEN too */
+ ParseEPD (token[1]);
+ NewPosition();
+}
+
+void cmd_solve(void) { Solve (token[1]); }
+
+/* Set total time for move to be N seconds is "st N" */
+void cmd_st(void)
+{
+ /* Approximately level 1 0 N */
+ sscanf(token[1],"%d",&TCinc);
+ suddendeath = 0 ;
+ /* Allow a little fussiness for failing low etc */
+ SearchTime = TCinc * 0.90f ;
+ CLEAR (flags, TIMECTL);
+}
+
+void cmd_switch(void)
+{
+ board.side = 1^board.side;
+ board.ep = -1 ; /* Enpassant doesn't apply after switch */
+ printf ("%s to move\n", board.side == white ? "White" : "Black");
+}
+
+void cmd_time(void)
+{
+ TimeLimit[1^board.side] = atoi(token[1]) / 100.0f ;
+}
+
+void cmd_undo(void)
+{
+ if (GameCnt >= 0)
+ UnmakeMove (board.side, &Game[GameCnt].move);
+ else
+ printf ("No moves to undo! \n");
+ MoveLimit[board.side]++;
+ TimeLimit[board.side] += Game[GameCnt+1].et;
+ if (!(flags & XBOARD)) ShowBoard ();
+}
+
+void cmd_usage(void)
+{
+ printf (
+ "\n"
+ " Usage: %s [OPTION]\n"
+ "\n"
+ " -h, --help display this help and exit\n"
+ " -v, --version display version information and exit\n"
+ "\n"
+ " -x, --xboard start in engine mode\n"
+ " -p, --post start up showing thinking\n"
+ " -e, --easy disable thinking in opponents time\n"
+ " -m, --manual enable manual mode\n"
+ " -s size, --hashsize=size specify hashtable size in slots\n"
+ "\n"
+ " Options xboard and post are accepted without leading dashes\n"
+ " for backward compatibility\n"
+ "\n"
+ "Report bugs to <bug-gnu-chess gnu org>.\n"
+ "\n", progname);
+ }
+
+
+/* Play variant, we instruct interface in protover we play normal */
+void cmd_variant(void) {}
+
+void cmd_version(void)
+{
+ if (!(flags & XBOARD))
+ printf ("%s %s\n", PROGRAM, VERSION);
+ else
+ printf ("Chess\n");
+}
+
+void cmd_white(void)
+{
+ /*
+ * No longer used by Xboard but requested as a feature
+ */
+
+ NewPosition(); /* Reset some flags and settings */
+ CLEAR ( flags, THINK);
+ CLEAR ( flags, MANUAL);
+ CLEAR (flags, TIMEOUT);
+ computer = black;
+ if ( board.side == black ){
+ board.side = white;
+ board.ep = -1; /* Hack to fixed appearing pawn bug */
+ }
+}
+
+void cmd_xboard(void)
+{
+ if (tokeneq (token[1], "off"))
+ CLEAR (flags, XBOARD);
+ else if (tokeneq (token[1], "on"))
+ SET (flags, XBOARD);
+ else if (!(flags & XBOARD)) { /* set if unset and only xboard called */
+ SET (flags, XBOARD); /* like in xboard/winboard usage */
+ }
+}
+
+/*
+ * Command with subcommands, could write secondary method
+ * tables here
+ */
+
+void cmd_show (void)
+/************************************************************************
+ *
+ * The show command driver section.
+ *
+ ************************************************************************/
+{
+ if (tokeneq (token[1], "board"))
+ ShowBoard ();
+ else if (tokeneq (token[1], "rating"))
+ {
+ printf("My rating = %d\n",myrating);
+ printf("Opponent rating = %d\n",opprating);
+ }
+ else if (tokeneq (token[1], "time"))
+ ShowTime ();
+ else if (tokeneq (token[1], "moves")) {
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenMoves (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %ld\n", GenCnt);
+ }
+ else if (tokeneq (token[1], "escape")) {
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenCheckEscapes (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %ld\n", GenCnt);
+ }
+ else if (tokeneq (token[1], "noncapture"))
+ {
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenNonCaptures (1);
+ FilterIllegalMoves (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %ld\n", GenCnt);
+ }
+ else if (tokeneq (token[1], "capture"))
+ {
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenCaptures (1);
+ FilterIllegalMoves (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %ld\n", GenCnt);
+ }
+ else if (tokeneq (token[1], "eval") || tokeneq (token[1], "score"))
+ {
+ int s, wp, bp, wk, bk;
+ BitBoard *b;
+
+ phase = PHASE;
+ GenAtaks ();
+ FindPins (&pinned);
+ hunged[white] = EvalHung(white);
+ hunged[black] = EvalHung(black);
+ b = board.b[white];
+ pieces[white] = b[knight] | b[bishop] | b[rook] | b[queen];
+ b = board.b[black];
+ pieces[black] = b[knight] | b[bishop] | b[rook] | b[queen];
+ wp = ScoreP (white);
+ bp = ScoreP (black);
+ wk = ScoreK (white);
+ bk = ScoreK (black);
+ printf ("White: Mat:%4d/%4d P:%d N:%d B:%d R:%d Q:%d K:%d Dev:%d h:%d x:%d\n",
+ board.pmaterial[white], board.material[white], wp, ScoreN(white),
+ ScoreB(white), ScoreR(white), ScoreQ(white), wk,
+ ScoreDev(white), hunged[white], ExchCnt[white]);
+ printf ("Black: Mat:%4d/%4d P:%d N:%d B:%d R:%d Q:%d K:%d Dev:%d h:%d x:%d\n",
+ board.pmaterial[black], board.material[black], bp, ScoreN(black),
+ ScoreB(black), ScoreR(black), ScoreQ(black), bk,
+ ScoreDev(black), hunged[black], ExchCnt[black]);
+ printf ("Phase: %d\t", PHASE);
+ s = ( EvaluateDraw () ? DRAWSCORE : Evaluate (-INFINITY, INFINITY));
+ printf ("score = %d\n", s);
+ printf ("\n");
+ }
+ else if (tokeneq (token[1], "game"))
+ ShowGame ();
+ else if (tokeneq (token[1], "pin"))
+ {
+ BitBoard b;
+ GenAtaks ();
+ FindPins (&b);
+ ShowBitBoard (&b);
+ }
+}
+
+void cmd_test (void)
+/*************************************************************************
+ *
+ * The test command driver section.
+ *
+ *************************************************************************/
+{
+ if (tokeneq (token[1], "movelist"))
+ TestMoveList ();
+ else if (tokeneq (token[1], "capture"))
+ TestCaptureList ();
+ else if (tokeneq (token[1], "movegenspeed"))
+ TestMoveGenSpeed ();
+ else if (tokeneq (token[1], "capturespeed"))
+ TestCaptureGenSpeed ();
+ else if (tokeneq (token[1], "eval"))
+ TestEval ();
+ else if (tokeneq (token[1], "evalspeed"))
+ TestEvalSpeed ();
+}
+
+/*
+ * This is more or less copied from the readme, and the
+ * parser is not very clever, so the lines containing
+ * command names should not be indented, the lines with
+ * explanations following them should be indented. Do not
+ * use tabs for indentation, only spaces. CAPITALS are
+ * reserved for parameters in the command names. The
+ * array must be terminated by two NULLs.
+ *
+ * This one should be integrated in the method table.
+ * (Very much like docstrings in Lisp.)
+ */
+
+static const char * const helpstr[] = {
+ "^C",
+ " Typically the interrupt key stops a search in progress,",
+ " makes the move last considered best and returns to the",
+ " command prompt",
+ "quit",
+ " quit the program.",
+ "exit",
+ " In analysis mode this stops analysis, otherwise it quits the program.",
+ "help",
+ " Produces a help blurb corresponding to this list of commands.",
+ "book",
+ " add - compiles book.dat from book.pgn",
+ " on - enables use of book",
+ " off - disables use of book",
+ " worst - play worst move from book",
+ " best - play best move from book",
+ " prefer - default, same as 'book on'",
+ " random - play any move from book",
+ "version",
+ " prints out the version of this program",
+ "pgnsave FILENAME",
+ " saves the game so far to the file from memory",
+ "pgnload FILENAME",
+ " loads the game in the file into memory",
+ "force",
+ "manual",
+ " Makes the program stop moving. You may now enter moves",
+ " to reach some position in the future.",
+ " ",
+ "white",
+ " Program plays white",
+ "black",
+ " Program plays black",
+ "go",
+ " Computer takes whichever side is on move and begins its",
+ " thinking immediately",
+ "post",
+ " Arranges for verbose thinking output showing variation, score,",
+ " time, depth, etc.",
+ "nopost",
+ " Turns off verbose thinking output",
+ "name NAME",
+ " Lets you input your name. Also writes the log.nnn and a",
+ " corresponding game.nnn file. For details please see",
+ " auxillary file format sections.",
+ "result",
+ " Mostly used by Internet Chess server.",
+ "activate",
+ " This command reactivates a game that has been terminated automatically",
+ " due to checkmate or no more time on the clock. However, it does not",
+ " alter those conditions. You would have to undo a move or two or",
+ " add time to the clock with level or time in that case.",
+ "rating COMPUTERRATING OPPONENTRATING",
+ " Inputs the estimated rating for computer and for its opponent",
+ "new",
+ " Sets up new game (i.e. positions in original positions)",
+ "time",
+ " Inputs time left in game for computer in hundredths of a second.",
+ " Mostly used by Internet Chess server.",
+ "hash",
+ " on - enables using the memory hash table to speed search",
+ " off - disables the memory hash table",
+ "hashsize N",
+ " Sets the hash table to permit storage of N positions",
+ "null",
+ " on - enables using the null move heuristic to speed search",
+ " off - disables using the null move heuristic",
+ "xboard",
+ " on - enables use of xboard/winboard",
+ " off - disables use of xboard/winboard",
+ "depth N",
+ " Sets the program to look N ply (half-moves) deep for every",
+ " search it performs. If there is a checkmate or other condition",
+ " that does not allow that depth, then it will not be ",
+ "level MOVES MINUTES INCREMENT",
+ " Sets time control to be MOVES in MINUTES with each move giving",
+ " an INCREMENT (in seconds, i.e. Fischer-style clock).",
+ "load",
+ "epdload",
+ " Loads a position in EPD format from disk into memory.",
+ "save",
+ "epdsave",
+ " Saves game position into EPD format from memory to disk.",
+ "switch",
+ " Switches side to move",
+ "solve FILENAME",
+ "solveepd FILENAME",
+ " Solves the positions in FILENAME",
+ "remove",
+ " Backs up two moves in game history",
+ "undo",
+ " Backs up one move in game history",
+ "usage",
+ " Display command line syntax",
+ "show",
+ " board - displays the current board",
+ " time - displays the time settings",
+ " moves - shows all moves using one call to routine",
+ " escape - shows moves that escape from check using one call to routine",
+ " noncapture - shows non-capture moves",
+ " capture - shows capture moves",
+ " eval [or score] - shows the evaluation per piece and overall",
+ " game - shows moves in game history",
+ " pin - shows pinned pieces",
+ "test",
+ " movelist - reads in an epd file and shows legal moves for its entries",
+ " capture - reads in an epd file and shows legal captures for its entries",
+ " movegenspeed - tests speed of move generator",
+ " capturespeed - tests speed of capture move generator",
+ " eval - reads in an epd file and shows evaluation for its entries",
+ " evalspeed tests speed of the evaluator",
+ "bk",
+ " show moves from opening book.",
+ NULL,
+ NULL
+};
+
+void cmd_help (void)
+/**************************************************************************
+ *
+ * Display all the help commands.
+ *
+ **************************************************************************/
+{
+ const char * const *p;
+ int count, len;
+
+ if (strlen(token[1])>0) {
+ for (p=helpstr, count=0; *p; p++) {
+ if (strncmp(*p, token[1], strlen(token[1])) == 0) {
+ puts(*p);
+ while (*++p && **p != ' ') /* Skip aliases */ ;
+ for (; *p && **p == ' '; p++) {
+ puts(*p);
+ }
+ return;
+ }
+ }
+ printf("Help for command %s not found\n\n", token[1]);
+ }
+ printf("List of commands: (help COMMAND to get more help)\n");
+ for (p=helpstr, count=0; *p; p++) {
+ len = strcspn(*p, " ");
+ if (len > 0) {
+ count += printf("%.*s ", len, *p);
+ if (count > 60) {
+ count = 0;
+ puts("");
+ }
+ }
+ }
+ puts("");
+}
+
+/*
+ * Try a method table, one could also include the documentation
+ * strings here
+ */
+
+struct methodtable {
+ const char *name;
+ void (*method) (void);
+};
+
+/* Last entry contains to NULL pointers */
+
+/* List commands we don't implement to avoid illegal moving them */
+
+const struct methodtable commands[] = {
+ { "?", cmd_movenow },
+ { "accepted", cmd_accepted },
+ { "activate", cmd_activate },
+ { "analyze", cmd_analyze },
+ { "bk", cmd_bk },
+ { "black", cmd_black },
+ { "book", cmd_book },
+ { "computer", cmd_computer },
+ { "depth", cmd_depth },
+ { "draw", cmd_draw },
+ { "easy", cmd_easy },
+ { "edit", cmd_edit },
+ { "epd", cmd_epd },
+ { "epdload", cmd_load },
+ { "epdsave", cmd_save },
+ { "exit", cmd_exit },
+ { "force", cmd_force },
+ { "go", cmd_go },
+ { "hard", cmd_hard },
+ { "hash", cmd_hash },
+ { "hashsize", cmd_hashsize },
+ { "help", cmd_help },
+ { "hint", cmd_hint },
+ { "level", cmd_level },
+ { "list", cmd_list },
+ { "load", cmd_load },
+ { "manual", cmd_manual },
+ { "name", cmd_name },
+ { "new", cmd_new },
+ { "nopost", cmd_nopost },
+ { "null", cmd_null },
+ { "otim", cmd_otim },
+ { "pgnload", cmd_pgnload },
+ { "pgnsave", cmd_pgnsave },
+ { "ping", cmd_ping },
+ { "post", cmd_post },
+ { "protover", cmd_protover },
+ { "quit", cmd_quit },
+ { "random", cmd_random },
+ { "rating", cmd_rating },
+ { "rejected", cmd_rejected },
+ { "remove", cmd_remove },
+ { "result", cmd_result },
+ { "save", cmd_save },
+ { "setboard", cmd_setboard },
+ { "show", cmd_show },
+ { "solve", cmd_solve },
+ { "solveepd", cmd_solve },
+ { "st", cmd_st },
+ { "switch", cmd_switch },
+ { "test", cmd_test },
+ { "time", cmd_time },
+ { "undo", cmd_undo },
+ { "usage", cmd_usage },
+ { "variant", cmd_variant },
+ { "version", cmd_version },
+ { "white", cmd_white },
+ { "xboard", cmd_xboard },
+ { NULL, NULL }
+};
+
+void parse_input(void)
+/*************************************************************************
+ *
+ * This is the main user command interface driver.
+ *
+ *************************************************************************/
+{
+ leaf *ptr;
+ const struct methodtable * meth;
+
+ dbg_printf("parse_input() called, inputstr = *%s*\n", inputstr);
+
+ split_input();
+
+ for (meth = commands; meth->name != NULL; meth++) {
+ if (tokeneq(token[0], meth->name)) {
+ meth->method();
+ return;
+ }
+ }
+
+ /* OK, no known command, this should be a move */
+ ptr = ValidateMove (token[0]);
+ if (ptr != NULL) {
+ SANMove (ptr->move, 1);
+ MakeMove (board.side, &ptr->move);
+ strcpy (Game[GameCnt].SANmv, SANmv);
+ printf("%d. ",GameCnt/2+1);
+ printf("%s",token[0]);
+ if (ofp != stdout) {
+ fprintf(ofp,"%d. ",GameCnt/2+1);
+ fprintf(ofp,"%s",token[0]);
+ }
+ putchar('\n');
+ fflush(stdout);
+ if (ofp != stdout) {
+ fputc('\n',ofp);
+ fflush(ofp);
+ }
+ if (!(flags & XBOARD)) ShowBoard ();
+ SET (flags, THINK);
+ }
+ else {
+ /*
+ * Must Output Illegal move to prevent Xboard accepting illegal
+ * en passant captures and other subtle mistakes
+ */
+ printf("Illegal move: %s\n",token[0]);
+ fflush(stdout);
+ }
+}
+
diff --git a/src/chess_computer-activity/gnuchess/common.h b/src/chess_computer-activity/gnuchess/common.h
new file mode 100644
index 0000000..d846d93
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/common.h
@@ -0,0 +1,860 @@
+/* GNU Chess 5.0 - common.h - common symbolic definitions
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <config.h>
+
+#ifndef __GNUC__
+# define __attribute__(x)
+#endif
+
+/*
+ * Include "uint64_t" and similar types using the ac_need_stdint_h ac macro
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+ /*
+ * Define time structures to get timeval for Timer
+ */
+
+#include <sys/time.h>
+
+ /*
+ * Define macro for declaring 64bit constants for compilers not using ULL
+ */
+
+#ifdef _MSC_VER
+ #define ULL(x) ((uint64_t)(x))
+#else
+ #define ULL(x) x ## ULL
+#endif
+
+/*
+ * BitBoard is a key data type. It is a 64-bit value, in which each
+ * bit represents a square on the board as defined by "enum Square".
+ * Thus, bit position 0 represents a fact about square a1, and bit
+ * position 63 represents a fact about square h8. For example, the
+ * bitboard representing "white rook" positions will have a bit set
+ * for every position occupied on the board by a white rook.
+ */
+
+typedef uint64_t BitBoard;
+typedef uint64_t HashType;
+typedef uint32_t KeyType;
+
+/*
+ * Board represents an entire board's state, and is structured to
+ * simplify analysis:
+ */
+
+typedef struct
+{
+ BitBoard b[2][7]; /* piece/pawn positions by side (0=white, 1=black)
+ and then by piece (1=pawn..6=king). For example,
+ b[white][knight] has bits set for every board
+ position occupied by a White Knight. */
+ BitBoard friends[2]; /* Friendly (this side's) pieces */
+ BitBoard blocker;
+ BitBoard blockerr90; /* rotated 90 degrees */
+ BitBoard blockerr45; /* rotated 45 degrees */
+ BitBoard blockerr315; /* rotated 315 degrees */
+ short ep; /* Location of en passant square */
+ short flag; /* Flags related to castle privileges */
+ short side; /* Color of side on move: 0=white, 1=black */
+ short material[2]; /* Total material by side not inc. king */
+ short pmaterial[2]; /* Total pawn material by side not inc. king */
+ short castled[2]; /* True (1) if side is castled */
+ short king[2]; /* Location of king 0 - a1 .. 63 - h8 */
+} Board;
+
+/* leaf describes a leaf-level analysis result */
+
+typedef struct
+{
+ int move; /* the move that produced this particular board */
+ int score; /* the scored value of this leaf */
+} leaf;
+
+/*
+ * GameRec records an individual move made in the game; an entire
+ * Game is a set of GameRec's:
+ */
+
+#define SANSZ 8 /* longest move is "exf8=Q+" so 7+1 */
+
+typedef struct
+{
+ int move; /* The actual move made; this is NOT the move count! */
+ short epsq; /* en passant square */
+ short bflag; /* Flags for castle privs, see Board.flag */
+ short Game50; /* The last value of GameCnt (a count of half-moves)
+ that castled, captured, or moved a pawn */
+ short mvboard;
+ float et; /* elapsed time */
+ HashType hashkey;
+ HashType phashkey;
+ char SANmv[SANSZ]; /* The move in SAN notation */
+ char *comments;
+} GameRec;
+
+typedef struct
+{
+ HashType key; /* Full 64 bit hash */
+ int move; /* Best move */
+ int score; /* Estimated score, may be lower or upper bound */
+ uint8_t flag; /* Is this alpha, beta, quiescent or exact? */
+ uint8_t depth; /* Search depth */
+} HashSlot;
+
+typedef struct
+{
+ KeyType pkey;
+ BitBoard passed;
+ BitBoard weaked;
+ int score;
+ int phase;
+} PawnSlot;
+
+
+/* MACRO definitions */
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#define SET(a,b) \
+ do { \
+ (a) |= (b); \
+ dbg_printf("Set 0x%x\n", (b)); \
+ } while (0)
+#define CLEAR(a,b) \
+ do { \
+ (a) &= ~(b); \
+ dbg_printf("Clear 0x%x\n", (b)); \
+ } while (0)
+
+/* Draw score can be used to penalise draws if desired */
+#define DRAWSCORE 0
+#define MATERIAL (board.material[side] - board.material[1^side])
+#define PHASE (8 - (board.material[white]+board.material[black]) / 1150)
+#define KEY(a) (a >> 32)
+
+/* Attack MACROS */
+
+#define BishopAttack(sq) \
+ (Bishop45Atak[sq][(board.blockerr45 >> Shift45[sq]) & Mask45[sq]] | \
+ Bishop315Atak[sq][(board.blockerr315 >> Shift315[sq]) & Mask315[sq]])
+#define RookAttack(sq) \
+ (Rook00Atak[sq][(board.blocker >> Shift00[sq]) & 0xFF] | \
+ Rook90Atak[sq][(board.blockerr90 >> Shift90[sq]) & 0xFF])
+#define QueenAttack(sq) \
+ (BishopAttack(sq) | RookAttack(sq))
+
+
+/* Some bit macros */
+
+/*
+ * gcc 2.95.4 completely screws up the macros with lookup tables
+ * with -O2 on PPC, maybe this check has to be refined. (I don't know
+ * whether other architectures also suffer from this gcc bug.) However,
+ * with gcc 3.0, the lookup tables are _much_ faster than this direct
+ * calculation.
+ */
+#if defined(__GNUC__) && defined(__PPC__) && __GNUC__ < 3
+# define SETBIT(b,i) ((b) |= ((ULL(1)<<63)>>(i)))
+# define CLEARBIT(b,i) ((b) &= ~((ULL(1)<<63)>>(i)))
+#else
+# define SETBIT(b,i) ((b) |= BitPosArray[i])
+# define CLEARBIT(b,i) ((b) &= NotBitPosArray[i])
+#endif
+
+#define RANK(i) ((i) >> 3)
+#define ROW(i) ((i) & 7)
+#define trailz(b) (leadz ((b) & ((~b) + 1)))
+
+/* Move Descriptions (moves) are represented internally as integers.
+ * The lowest 6 bits define the destination ("TO") square, and
+ * the next lowest 6 bits define the source ("FROM") square,
+ * using the values defined by "enum Square" (0=a1, 63=h8).
+ * Upper bits are used to identify other move information such as
+ * a promotion (and to what), a capture (and of what),
+ * CASTLING moves, and ENPASSANT moves; see the "constants for
+ * move description" below for more information on these upper bits.
+ */
+#define PROMOTEPIECE(a) ((a >> 12) & 0x0007)
+#define CAPTUREPIECE(a) ((a >> 15) & 0x0007)
+#define TOSQ(a) ((a) & 0x003F)
+#define FROMSQ(a) ((a >> 6) & 0x003F)
+#define MOVE(a,b) (((a) << 6) | (b))
+
+/* constants for move description */
+#define KNIGHTPRM 0x00002000
+#define BISHOPPRM 0x00003000
+#define ROOKPRM 0x00004000
+#define QUEENPRM 0x00005000
+#define PROMOTION 0x00007000
+#define PAWNCAP 0x00008000
+#define KNIGHTCAP 0x00010000
+#define BISHOPCAP 0x00018000
+#define ROOKCAP 0x00020000
+#define QUEENCAP 0x00028000
+#define CAPTURE 0x00038000
+#define NULLMOVE 0x00100000
+#define CASTLING 0x00200000
+#define ENPASSANT 0x00400000
+#define MOVEMASK (CASTLING | ENPASSANT | PROMOTION | 0x0FFF)
+
+#define white 0
+#define black 1
+#define false 0
+#define true 1
+#define ks 0
+#define qs 1
+#define INFINITY 32767
+#define MATE 32767
+#define MATESCORE(a) ((a) > MATE-255 || (a) < -MATE+255)
+
+/* constants for Board */
+#define WKINGCASTLE 0x0001
+#define WQUEENCASTLE 0x0002
+#define BKINGCASTLE 0x0004
+#define BQUEENCASTLE 0x0008
+#define WCASTLE (WKINGCASTLE | WQUEENCASTLE)
+#define BCASTLE (BKINGCASTLE | BQUEENCASTLE)
+
+/* Material values */
+#define ValueP 100
+#define ValueN 350
+#define ValueB 350
+#define ValueR 550
+#define ValueQ 1100
+#define ValueK 2000
+
+
+/* Some special BitBoards */
+#define NULLBITBOARD ( ULL(0x0000000000000000))
+#define WHITESQUARES ( ULL(0x55AA55AA55AA55AA))
+#define BLACKSQUARES ( ULL(0xAA55AA55AA55AA55))
+#define CENTRESQUARES ( ULL(0x0000001818000000))
+#define COMPUTERHALF ( ULL(0xFFFFFFFF00000000))
+#define OPPONENTHALF ( ULL(0x00000000FFFFFFFF))
+
+/* Game flags */
+#define QUIT 0x0001
+#define TESTT 0x0002
+#define THINK 0x0004
+#define MANUAL 0x0008
+#define TIMEOUT 0x0010
+#define SPARE1 0x0020
+#define ENDED 0x0040
+#define USEHASH 0x0080
+#define SOLVE 0x0100
+#define USENULL 0x0200
+#define XBOARD 0x0400
+#define TIMECTL 0x0800
+#define POST 0x1000
+#define PONDER 0x2000 /* We are in pondering (during search) */
+#define HARD 0x4000 /* Pondering is turned on */
+#define ANALYZE 0x8000 /* In ANALYZE mode */
+
+/* Node types */
+#define PV 0
+#define ALL 1
+#define CUT 2
+
+/* Transposition table flags */
+#define EXACTSCORE 1
+#define LOWERBOUND 2
+#define UPPERBOUND 3
+#define POORDRAFT 4
+#define QUIESCENT 5
+#define STICKY 8
+
+/* Book modes */
+#define BOOKOFF 0
+#define BOOKRAND 1
+#define BOOKBEST 2
+#define BOOKWORST 3
+#define BOOKPREFER 4
+
+/* The various phases during move selection */
+#define PICKHASH 1
+#define PICKGEN1 2
+#define PICKCAPT 3
+#define PICKKILL1 4
+#define PICKKILL2 5
+#define PICKGEN2 6
+#define PICKHIST 7
+#define PICKREST 8
+#define PICKCOUNTER 9
+
+#define MAXTREEDEPTH 2000
+#define MAXPLYDEPTH 65
+#define MAXGAMEDEPTH 600
+
+/*
+ Smaller HASHSLOT defaults 20011017 to improve blitz play
+ and make it easier to run on old machines
+*/
+#define HASHSLOTS 1024
+#define PAWNSLOTS 512
+
+extern short distance[64][64];
+extern short taxicab[64][64];
+extern unsigned char lzArray[65536];
+extern short Shift00[64];
+extern short Shift90[64];
+extern short Shift45[64];
+extern short Shift315[64];
+extern BitBoard DistMap[64][8];
+extern BitBoard BitPosArray[64];
+extern BitBoard NotBitPosArray[64];
+extern BitBoard MoveArray[8][64];
+extern BitBoard Ray[64][8];
+extern BitBoard FromToRay[64][64];
+extern BitBoard RankBit[8];
+extern BitBoard FileBit[8];
+extern BitBoard Ataks[2][7];
+extern BitBoard PassedPawnMask[2][64];
+extern BitBoard IsolaniMask[8];
+extern BitBoard SquarePawnMask[2][64];
+extern BitBoard Rook00Atak[64][256];
+extern BitBoard Rook90Atak[64][256];
+extern BitBoard Bishop45Atak[64][256];
+extern BitBoard Bishop315Atak[64][256];
+extern BitBoard pinned;
+extern BitBoard rings[4];
+extern BitBoard boxes[2];
+extern BitBoard stonewall[2];
+extern BitBoard pieces[2];
+extern BitBoard mask_kr_trapped_w[3];
+extern BitBoard mask_kr_trapped_b[3];
+extern BitBoard mask_qr_trapped_w[3];
+extern BitBoard mask_qr_trapped_b[3];
+extern BitBoard boardhalf[2];
+extern BitBoard boardside[2];
+extern short directions[64][64];
+extern unsigned char BitCount[65536];
+extern leaf Tree[MAXTREEDEPTH];
+extern leaf *TreePtr[MAXPLYDEPTH];
+extern int RootPV;
+extern GameRec Game[MAXGAMEDEPTH];
+extern int RealGameCnt;
+extern short RealSide;
+extern int GameCnt;
+extern int computer;
+extern unsigned int flags;
+extern unsigned int preanalyze_flags;
+extern Board board;
+extern int cboard[64];
+extern int Mvboard[64];
+extern HashType hashcode[2][7][64];
+extern HashType ephash[64];
+extern HashType WKCastlehash;
+extern HashType WQCastlehash;
+extern HashType BKCastlehash;
+extern HashType BQCastlehash;
+extern HashType Sidehash;
+extern HashType HashKey;
+extern HashType PawnHashKey;
+extern HashSlot *HashTab[2];
+extern PawnSlot *PawnTab[2];
+extern int Idepth;
+extern int SxDec;
+extern int Game50;
+extern int lazyscore[2];
+extern int maxposnscore[2];
+extern int rootscore;
+extern int lastrootscore;
+extern unsigned long GenCnt;
+extern unsigned long NodeCnt;
+extern unsigned long QuiesCnt;
+extern unsigned long EvalCnt;
+extern unsigned long EvalCall;
+extern unsigned long ChkExtCnt;
+extern unsigned long OneRepCnt;
+extern unsigned long RcpExtCnt;
+extern unsigned long PawnExtCnt;
+extern unsigned long HorzExtCnt;
+extern unsigned long ThrtExtCnt;
+extern unsigned long KingExtCnt;
+extern unsigned long NullCutCnt;
+extern unsigned long FutlCutCnt;
+extern unsigned long RazrCutCnt;
+extern unsigned long TotalGetHashCnt;
+extern unsigned long GoodGetHashCnt;
+extern unsigned long TotalPutHashCnt;
+extern unsigned long CollHashCnt;
+extern unsigned long TotalPawnHashCnt;
+extern unsigned long GoodPawnHashCnt;
+extern unsigned long RepeatCnt;
+extern unsigned HashSize;
+extern unsigned long TTHashMask;
+extern unsigned long PHashMask;
+extern int slider[8];
+extern int Value[7];
+extern char SANmv[SANSZ];
+extern unsigned long history[2][4096];
+extern int killer1[MAXPLYDEPTH];
+extern int killer2[MAXPLYDEPTH];
+extern int ChkCnt[MAXPLYDEPTH];
+extern int ThrtCnt[MAXPLYDEPTH];
+extern char id[32];
+extern char solution[64];
+extern float SearchTime;
+extern int SearchDepth;
+extern int MoveLimit[2];
+extern float TimeLimit[2];
+extern int TCMove;
+extern int TCinc;
+extern float TCTime;
+extern int hunged[2];
+extern int phase;
+extern int Hashmv[MAXPLYDEPTH];
+extern short RootPieces;
+extern short RootPawns;
+extern short RootMaterial;
+extern short RootAlpha;
+extern short RootBeta;
+extern short pickphase[MAXPLYDEPTH];
+extern short InChk[MAXPLYDEPTH];
+extern short KingThrt[2][MAXPLYDEPTH];
+extern short KingSafety[2];
+extern short pscore[64];
+
+extern short bookmode;
+extern short bookfirstlast;
+
+extern int range[8];
+extern int ptype[2];
+extern char algbr[64][3];
+extern char algbrfile[9];
+extern char algbrrank[9];
+extern char notation[8];
+extern char lnotation[8];
+extern int r90[64];
+extern int r45[64];
+extern int r315[64];
+extern int Mask45[64];
+extern int Mask315[64];
+
+extern int rank6[2];
+extern int rank7[2];
+extern int rank8[2];
+
+extern char *progname;
+extern FILE *ofp;
+extern int myrating, opprating, suddendeath;
+
+#define MAXNAMESZ 50
+extern char name[MAXNAMESZ];
+extern int computerplays;
+extern int wasbookmove;
+extern int nmovesfrombook;
+extern float maxtime;
+extern int n; /* Last mobility returned by CTL */
+extern int ExchCnt[2];
+extern int newpos, existpos; /* For book statistics */
+extern int bookloaded;
+
+enum Piece { empty, pawn, knight, bishop, rook, queen, king, bpawn };
+
+enum Square { A1, B1, C1, D1, E1, F1, G1, H1,
+ A2, B2, C2, D2, E2, F2, G2, H2,
+ A3, B3, C3, D3, E3, F3, G3, H3,
+ A4, B4, C4, D4, E4, F4, G4, H4,
+ A5, B5, C5, D5, E5, F5, G5, H5,
+ A6, B6, C6, D6, E6, F6, G6, H6,
+ A7, B7, C7, D7, E7, F7, G7, H7,
+ A8, B8, C8, D8, E8, F8, G8, H8 };
+
+enum File { A_FILE, B_FILE, C_FILE, D_FILE, E_FILE, F_FILE, G_FILE, H_FILE };
+
+/****************************************************************************
+ *
+ * The various function prototypes. They are group into the *.c files
+ * in which they are defined.
+ *
+ ****************************************************************************/
+
+/*
+ * Explanation of the #ifdef NO_INLINE conditionals:
+ *
+ * Define NO_INLINE only if you really must, implementations will be
+ * provided by the corresponding *.c files. The better solution is to
+ * not define it, in which case inlines.h will be included which
+ * provides static inline version of these functions.
+ */
+
+/* The initialization routines */
+void Initialize (void);
+void InitLzArray (void);
+void InitBitPosArray (void);
+void InitMoveArray (void);
+void InitRay (void);
+void InitFromToRay (void);
+void InitRankFileBit (void);
+void InitBitCount (void);
+void InitPassedPawnMask (void);
+void InitIsolaniMask (void);
+void InitSquarePawnMask (void);
+void InitRandomMasks (void);
+void InitRotAtak (void);
+void InitDistance (void);
+void InitVars (void);
+void InitHashCode (void);
+void InitHashTable (void);
+void CalcHashSize (int);
+void NewPosition (void);
+void InitFICS (void);
+void InitInput (void);
+
+/* Cleanup routines */
+void CleanupInput(void);
+
+/* The book routines */
+int BookQuery (int);
+int BookBuilderOpen(void);
+int BookBuilder (short result, uint8_t side);
+int BookBuilderClose(void);
+
+/*
+ * Return values (errorcodes) for the book routines,
+ * maybe one should have a global enum of errorcodes
+ */
+enum {
+ BOOK_SUCCESS,
+ BOOK_EFORMAT, /* Wrong format (e.g. produced by older version) */
+ BOOK_EMIDGAME, /* Move is past the opening book's move limit */
+ BOOK_EIO, /* I/O error, e.g. caused by wrong permissions */
+ BOOK_EFULL, /* Book hash is full, new position was not added. */
+ BOOK_ENOBOOK, /* No book present */
+ BOOK_ENOMOVES, /* No moves found (in BookQuery() only) */
+ BOOK_ENOMEM /* Memory allocation failed */
+};
+
+/* The move generation routines */
+void GenMoves (short);
+void GenCaptures (short);
+void GenNonCaptures (short);
+void GenCheckEscapes (short);
+void FilterIllegalMoves (short);
+
+/* The move routines */
+void MakeMove (int, int *);
+void UnmakeMove (int, int *);
+void MakeNullMove (int);
+void UnmakeNullMove (int);
+void SANMove (int, int);
+leaf *ValidateMove (char *);
+leaf *IsInMoveList (int, int, int, char);
+int IsLegalMove (int);
+char *AlgbrMove (int);
+
+/* The attack routines */
+short SqAtakd (short sq, short side);
+void GenAtaks (void);
+BitBoard AttackTo (int, int);
+BitBoard AttackXTo (int, int);
+BitBoard AttackFrom (int, int, int);
+BitBoard AttackXFrom (int, int);
+int PinnedOnKing (int, int);
+void FindPins (BitBoard *);
+int MateScan (int);
+
+/* The swap routines */
+int SwapOff (int);
+void AddXrayPiece (int, int, int, BitBoard *, BitBoard *);
+
+/* The EPD routines */
+short ReadEPDFile (const char *, short);
+int ParseEPD (char *);
+void LoadEPD (char *);
+void SaveEPD (char *);
+
+/* Error codes for ParseEPD */
+enum {
+ EPD_SUCCESS,
+ EPD_ERROR
+};
+
+void UpdateFriends (void);
+void UpdateCBoard (void);
+void UpdateMvboard (void);
+void EndSearch (int);
+short ValidateBoard (void);
+
+/* PGN routines */
+void PGNSaveToFile (const char *, const char *);
+void PGNReadFromFile (const char *);
+void BookPGNReadFromFile (const char *);
+int IsTrustedPlayer(const char *name);
+
+
+/* The hash routines */
+void CalcHashKey (void);
+void ShowHashKey (HashType);
+
+/* The evaluation routines */
+int ScoreP (short);
+int ScoreN (short);
+int ScoreB (short);
+int ScoreR (short);
+int ScoreQ (short);
+int ScoreK (short);
+int ScoreDev (short);
+int Evaluate (int, int);
+short EvaluateDraw (void);
+
+/* Hung routines */
+int EvalHung (int);
+
+/* The search routines */
+void Iterate (void);
+int Search (uint8_t ply, short depth, int alpha, int beta, short nodetype);
+int SearchRoot (short depth, int alpha, int beta);
+int Quiesce (uint8_t ply, int alpha, int beta);
+void pick (leaf *, short);
+short Repeat (void);
+void ShowLine (int, int, char);
+
+/*
+ * Set up a timer by first calling StartTiming(), saving
+ * the return value and feeding it to GetElapsed() for
+ * timings in seconds.
+ */
+typedef struct timeval Timer;
+extern double ElapsedTime;
+extern Timer StartTime;
+Timer StartTiming (void);
+double GetElapsed (Timer start);
+
+/* The transposition table routies */
+void TTPut (uint8_t side, uint8_t depth, uint8_t ply,
+ int alpha, int beta, int score, int move);
+/* Returns flag if it finds an entry, 0 otherwise */
+uint8_t TTGet (uint8_t side, uint8_t depth, uint8_t ply,
+ int *score, int *move);
+short TTGetPV (uint8_t side, uint8_t ply, int score, int *move);
+void TTClear (void);
+void PTClear (void);
+
+/* Sorting routines */
+void SortCaptures (int);
+void SortMoves (int);
+void SortRoot (void);
+int PhasePick (leaf **, int);
+int PhasePick1 (leaf **, int);
+
+/* Some output routines */
+void ShowMoveList (int);
+void ShowSmallBoard (void);
+void ShowBoard (void);
+void ShowBitBoard (BitBoard *);
+void ShowCBoard (void);
+void ShowMvboard (void);
+
+void ShowGame (void);
+void ShowTime (void);
+
+/* Random numbers routines */
+uint32_t Rand32 (void);
+HashType Rand64 (void);
+
+/* Solver routines */
+void Solve (char *);
+
+/* Test routines */
+void TestMoveGenSpeed (void);
+void TestNonCaptureGenSpeed (void);
+void TestCaptureGenSpeed (void);
+void TestMoveList (void);
+void TestNonCaptureList (void);
+void TestCaptureList (void);
+void TestEvalSpeed (void);
+void TestEval (void);
+
+/* Player database */
+void DBSortPlayer (const char *style);
+void DBListPlayer (const char *style);
+void DBReadPlayer (void);
+void DBWritePlayer (void);
+int DBSearchPlayer (const char *player);
+void DBUpdatePlayer (const char *player, const char *resultstr);
+void DBTest (void);
+
+/* Input thread and thread function */
+#include <pthread.h>
+extern pthread_t input_thread;
+void *input_func(void *);
+
+/*
+ * Status variable used by the input thread to signal
+ * pending input. Thought about using flags for this
+ * but this can be refined and is conceptually different
+ * from flags.
+ */
+enum {
+ INPUT_NONE,
+ INPUT_AVAILABLE
+};
+extern volatile int input_status;
+
+/*
+ * Function to wake up the input thread, should be called after
+ * input has been parsed.
+ */
+void input_wakeup(void);
+
+/* Wait for input. */
+
+void wait_for_input(void);
+
+/*
+ * Input routine, initialized to one of the specific
+ * input routines. The given argument is the prompt.
+ */
+void (*getline_intrl) (char *);
+
+#define MAXSTR 128
+extern char inputstr[MAXSTR];
+
+/* Input parser */
+void parse_input(void);
+
+/* Pondering */
+void ponder(void);
+
+/* The command subroutines */
+void ShowCmd (char *);
+void BookCmd (char *);
+void TestCmd (char *);
+
+/* Commands from the input engine */
+void cmd_accepted(void);
+void cmd_activate(void);
+void cmd_analyze(void);
+void cmd_bk(void);
+void cmd_black(void);
+void cmd_book(void);
+void cmd_computer(void);
+void cmd_depth(void);
+void cmd_draw(void);
+void cmd_easy(void);
+void cmd_edit(void);
+void cmd_epd(void);
+void cmd_exit(void);
+void cmd_force(void);
+void cmd_go(void);
+void cmd_hard(void);
+void cmd_hash(void);
+void cmd_hashsize(void);
+void cmd_help (void);
+void cmd_hint(void);
+void cmd_level(void);
+void cmd_list(void);
+void cmd_load(void);
+void cmd_manual(void);
+void cmd_movenow(void);
+void cmd_name(void);
+void cmd_new(void);
+void cmd_nopost(void);
+void cmd_null(void);
+void cmd_otim(void);
+void cmd_pgnload(void);
+void cmd_pgnsave(void);
+void cmd_ping(void);
+void cmd_post(void);
+void cmd_protover(void);
+void cmd_quit(void);
+void cmd_random(void);
+void cmd_rating(void);
+void cmd_rejected(void);
+void cmd_remove(void);
+void cmd_result(void);
+void cmd_save(void);
+void cmd_setboard(void);
+void cmd_show (void);
+void cmd_solve(void);
+void cmd_st(void);
+void cmd_switch(void);
+void cmd_test (void);
+void cmd_time(void);
+void cmd_undo(void);
+void cmd_usage(void);
+void cmd_variant(void);
+void cmd_version(void);
+void cmd_white(void);
+void cmd_xboard(void);
+
+/*
+ * Define NO_INLINE only if you really must, implementations will be
+ * provided by the corresponding *.c files. The better solution is to
+ * not define it, in which case inlines.h will be included which
+ * provides static inline version of these functions.
+ */
+
+/* Some utility routines */
+#ifdef NO_INLINE
+unsigned char leadz (BitBoard);
+unsigned char nbits (BitBoard);
+#else
+# include "inlines.h"
+#endif
+
+/* More elaborate debugging output to logfile */
+
+/* All the following functions are no-ops if DEBUG is not defined */
+
+/*
+ * dbg_open() can be called with NULL as argument, using a default
+ * filename, defined in debug.c, for the debug log. Otherwise the
+ * argument is the filename. If dbg_open() fails or is not called at
+ * all, debugging output goes to stderr by default.
+ */
+int dbg_open(const char *name);
+
+/* Same format rules as printf() */
+int dbg_printf(const char *fmt, ...);
+
+/* Closes the debugging log, if it is not stderr */
+int dbg_close(void);
+
+# ifdef DEBUG
+# include <assert.h>
+# define ASSERT(x) assert(x)
+# else
+# define ASSERT(x)
+# endif
+
+#endif /* !COMMON_H */
diff --git a/src/chess_computer-activity/gnuchess/debug.c b/src/chess_computer-activity/gnuchess/debug.c
new file mode 100644
index 0000000..761018a
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/debug.c
@@ -0,0 +1,74 @@
+/*
+ * debug.c - Debugging output
+ */
+
+#include <config.h>
+#include "common.h"
+
+#ifdef DEBUG
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#define MAX_DEBUG 1000
+#define DEBUG_FILENAME "gnuchess.debug"
+
+/* Default to stderr */
+static int debug_fd = 2;
+
+int dbg_open(const char *name)
+{
+ int flags = O_WRONLY | O_CREAT | O_APPEND;
+ int mode = 0777;
+
+ if (name == NULL) {
+ debug_fd = open(DEBUG_FILENAME, flags, mode);
+ } else {
+ debug_fd = open(name, flags, mode);
+ }
+ if (-1 == debug_fd) {
+ debug_fd = 2;
+ return -1;
+ }
+ dbg_printf("--- Opening debug log ---\n");
+ return debug_fd;
+}
+
+int dbg_close(void)
+{
+ /* We don't want to close stderr */
+ if (debug_fd == 2) {
+ return -1;
+ }
+ dbg_printf("--- Closing debug log ---\n");
+ return close(debug_fd);
+}
+
+int dbg_printf(const char *fmt, ...)
+{
+ va_list ap;
+ char buf[MAX_DEBUG];
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ sprintf(buf, "%010ld.%06ld: ", tv.tv_sec, tv.tv_usec);
+ write(debug_fd, buf, strlen(buf));
+
+ va_start(ap, fmt);
+ vsnprintf(buf, MAX_DEBUG, fmt, ap);
+ va_end(ap);
+
+ return write(debug_fd, buf, strlen(buf));
+}
+
+#else /* !DEBUG */
+
+int dbg_open(const char *name __attribute__((unused)) ) { return 0; }
+int dbg_printf(const char *fmt __attribute__((unused)), ...) { return 0; }
+int dbg_close(void) { return 0; }
+
+#endif /* DEBUG */
diff --git a/src/chess_computer-activity/gnuchess/epd.c b/src/chess_computer-activity/gnuchess/epd.c
new file mode 100644
index 0000000..97f76e4
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/epd.c
@@ -0,0 +1,370 @@
+/* GNU Chess 5.0 - epd.c - EPD position definition code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "common.h"
+
+#define EPDCLOSE 1
+
+short ReadEPDFile (const char *file, short op)
+/****************************************************************************
+ *
+ * Reads in an EPD file. The first call will read the first EPD line,
+ * the second call will read the 2nd line and so on. To improve
+ * performance, the file is never closed. Closing of the file happens
+ * only on 2 conditions: (i) A ReadEPDFile failed because there is no
+ * more lines to read. (ii) A called to ReadEPDFile to explicitly
+ * request that the file is closed (op = EPDCLOSE);
+ * If op == 2, then we work silently.
+ *
+ ****************************************************************************/
+{
+ static FILE *fp = NULL;
+ char line[MAXSTR];
+
+ /* If first time through, must open file */
+ if (fp == NULL)
+ {
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ {
+ printf ("Error opening file %s\n", file);
+ return (false);
+ }
+ }
+
+ /* Is this a close request? */
+ if (op == EPDCLOSE)
+ {
+ fclose (fp);
+ fp = NULL;
+ return (false);
+ }
+
+next_line:
+ /* Okay, we read in an EPD entry */
+ fgets (line, MAXSTR-1, fp);
+ if (!feof(fp))
+ {
+ int ret = ParseEPD (line);
+
+ /* For now just ignore malformed lines */
+ if (ret != EPD_SUCCESS) goto next_line;
+ if (op != 2)
+ printf ("\n%s : Best move = %s\n", id, solution);
+ return (true);
+ }
+ /* finished, must close file */
+ else
+ {
+ fclose (fp);
+ fp = NULL;
+ return (false);
+ }
+}
+
+/*
+ * Returns EPD_SUCCESS on success, EPD_ERROR on error. We try to be
+ * quite tough on the format. However, as of yet no legality checking
+ * is done and the board is not reset on error, this should be done by
+ * the caller.
+ */
+
+int ParseEPD (char *p)
+/**************************************************************************
+ *
+ * Parses an EPD input line. A few global variables are updated e.g.
+ * current board, side to move, en passant, castling status, etc.
+ *
+ **************************************************************************/
+{
+ int r, c, sq;
+ char *str_p;
+
+ r = 56;
+ c = 0;
+ memset (&board, 0, sizeof (board));
+
+ while (p && *p != ' ')
+ {
+ sq = r + c;
+ switch (*p)
+ {
+ case 'P' : SETBIT (board.b[white][pawn], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[white] += ValueP;
+ break;
+ case 'N' : SETBIT (board.b[white][knight], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[white] += ValueN;
+ break;
+ case 'B' : SETBIT (board.b[white][bishop], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[white] += ValueB;
+ break;
+ case 'R' : SETBIT (board.b[white][rook], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[white] += ValueR;
+ break;
+ case 'Q' : SETBIT (board.b[white][queen], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[white] += ValueQ;
+ break;
+ case 'K' : SETBIT (board.b[white][king], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ break;
+ case 'p' : SETBIT (board.b[black][pawn], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[black] += ValueP;
+ break;
+ case 'n' : SETBIT (board.b[black][knight], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[black] += ValueN;
+ break;
+ case 'b' : SETBIT (board.b[black][bishop], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[black] += ValueB;
+ break;
+ case 'r' : SETBIT (board.b[black][rook], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[black] += ValueR;
+ break;
+ case 'q' : SETBIT (board.b[black][queen], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ board.material[black] += ValueQ;
+ break;
+ case 'k' : SETBIT (board.b[black][king], sq);
+ SETBIT (board.blockerr90, r90[sq]);
+ SETBIT (board.blockerr45, r45[sq]);
+ SETBIT (board.blockerr315, r315[sq]);
+ break;
+ case '/' : r -= 8;
+ c = -1;
+ break;
+ default : break;
+ }
+ if (isdigit (*p))
+ c += (*p - '0');
+ else
+ c++;
+
+ /*
+ * Special case, a trailing "/" is accepted on the
+ * end of the board settings.
+ */
+
+ if (r == -8 && p[1] == ' ')
+ r = 0;
+
+ if (r < 0 || c > 8) return EPD_ERROR;
+ if (c == 8 && p[1] != '/' && p[1] != ' ') return EPD_ERROR;
+ p++;
+ }
+
+ board.pmaterial[white] = board.material[white] -
+ nbits(board.b[white][pawn]) * ValueP;
+ board.pmaterial[black] = board.material[black] -
+ nbits(board.b[black][pawn]) * ValueP;
+ board.king[white] = leadz (board.b[white][king]);
+ board.king[black] = leadz (board.b[black][king]);
+ UpdateFriends ();
+ UpdateCBoard ();
+ UpdateMvboard ();
+
+ /* Get side to move */
+ if (!++p) return EPD_ERROR;
+ if (*p == 'w') board.side = white;
+ else if (*p == 'b') board.side = black;
+ else return EPD_ERROR;
+
+ /* Isn't this one cute? */
+ if (!++p || *p != ' ' || !++p) return EPD_ERROR;
+
+ /* Castling status */
+ while (p && *p != ' ') {
+ if (*p == 'K') board.flag |= WKINGCASTLE;
+ else if (*p == 'Q') board.flag |= WQUEENCASTLE;
+ else if (*p == 'k') board.flag |= BKINGCASTLE;
+ else if (*p == 'q') board.flag |= BQUEENCASTLE;
+ else if (*p == '-') { p++; break; }
+ else return EPD_ERROR;
+ p++;
+ }
+ if (!p || *p != ' ' || !++p) return EPD_ERROR;
+
+ /*
+ * En passant square, can only be '-' or [a-h][36]
+ * In fact, one could add more sanity checks here.
+ */
+ if (*p != '-') {
+ if (!p[1] || *p < 'a' || *p > 'h' ||
+ !(p[1] == '3' || p[1] == '6')) return EPD_ERROR;
+ board.ep = (*p - 'a') + (p[1] - '1')*8;
+ p++;
+ } else {
+ board.ep = -1;
+ }
+
+ solution[0] = '\0';
+ id[0] = '\0';
+
+ if (!++p) return EPD_SUCCESS;
+
+ /* The opcodes are optional, so we should not generate errors here */
+
+ /* Read in best move; "bm" operator */
+ str_p = strstr(p, "bm");
+ if (str_p) sscanf (str_p, "bm %63[^;];", solution);
+
+ /* Read in the description; "id" operator */
+ str_p = strstr(p, "id");
+ if (str_p) sscanf (p, "id %31[^;];", id);
+
+ CalcHashKey ();
+ phase = PHASE;
+
+ return EPD_SUCCESS;
+}
+
+
+void LoadEPD (char *p)
+/**************************************************************************
+ *
+ * This routine reads in the next or the Nth position in the file.
+ *
+ **************************************************************************/
+{
+ char file[MAXSTR];
+ int N = 1;
+
+ sscanf (p, "%31s %d ", file, &N);
+ if (strcmp (file, "next") == 0)
+ {
+ ReadEPDFile (file, 0);
+ }
+ else
+ {
+ ReadEPDFile (file, 1);
+ while (--N)
+ {
+ if (ReadEPDFile (file, 2) == false)
+ {
+ printf ("File position exceeded\n");
+ return;
+ }
+ }
+ ReadEPDFile (file, 0);
+ }
+ ShowBoard ();
+ NewPosition ();
+}
+
+
+void SaveEPD (char *p)
+/**************************************************************************
+ *
+ * This routine appends the current position in EPD format into a file.
+ *
+ **************************************************************************/
+{
+ char file[MAXSTR];
+ FILE *fp;
+ int r, c, sq, k;
+ char c1;
+
+ sscanf (p, "%s ", file);
+ fp = fopen (file, "a");
+ for (r = A8; r >= A1; r -= 8)
+ {
+ k = 0;
+ for (c = 0; c < 8; c++)
+ {
+ sq = r + c;
+ if (cboard[sq] == empty)
+ k++;
+ else
+ {
+ if (k)
+ fprintf (fp, "%1d", k);
+ k = 0;
+ c1 = notation[cboard[sq]];
+ if (BitPosArray[sq] & board.friends[black])
+ c1 = tolower (c1);
+ fprintf (fp, "%c", c1);
+ }
+ }
+ if (k)
+ fprintf (fp, "%1d", k);
+ if (r > A1)
+ fprintf (fp, "/");
+ }
+
+ /* Print other stuff */
+ fprintf (fp, (board.side == white ? " w " : " b "));
+
+ if (board.flag & WKINGCASTLE)
+ fprintf (fp, "K");
+ if (board.flag & WQUEENCASTLE)
+ fprintf (fp, "Q");
+ if (board.flag & BKINGCASTLE)
+ fprintf (fp, "k");
+ if (board.flag & BQUEENCASTLE)
+ fprintf (fp, "q");
+ if (!(board.flag & (WCASTLE | BCASTLE)))
+ fprintf (fp, "-");
+
+ fprintf (fp, " %s", (board.ep > -1 ? algbr[board.ep] : "-"));
+ fprintf (fp, " bm 1; id 1;");
+ fprintf (fp, "\n");
+ fclose (fp);
+}
diff --git a/src/chess_computer-activity/gnuchess/eval.c b/src/chess_computer-activity/gnuchess/eval.c
new file mode 100644
index 0000000..c3e72ff
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/eval.c
@@ -0,0 +1,1496 @@
+/* GNU Chess 5.0 - eval.c - evaluation code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+/****************************************************************************
+ *
+ *
+ *
+ *****************************************************************************/
+
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "common.h"
+#include "eval.h"
+
+int LoneKing (int, int);
+int ScoreKBNK (int, int);
+int KPK (int);
+int BishopTrapped (short);
+int DoubleQR7 (short);
+
+BitBoard passed[2];
+BitBoard weaked[2];
+
+static int PawnSq[2][64] =
+{
+{ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5,-10,-10, 5, 5, 5,
+ -2, -2, -2, 6, 6, -2, -2, -2,
+ 0, 0, 0, 25, 25, 0, 0, 0,
+ 2, 2, 12, 16, 16, 12, 2, 2,
+ 4, 8, 12, 16, 16, 12, 4, 4,
+ 4, 8, 12, 16, 16, 12, 4, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0},
+{ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 8, 12, 16, 16, 12, 4, 4,
+ 4, 8, 12, 16, 16, 12, 4, 4,
+ 2, 2, 12, 16, 16, 12, 2, 2,
+ 0, 0, 0, 25, 25, 0, 0, 0,
+ -2, -2, -2, 6, 6, -2, -2, -2,
+ 5, 5, 5,-10,-10, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+static const int Passed[2][8] =
+{ { 0, 48, 48, 120, 144, 192, 240, 0}, {0, 240, 192, 144, 120, 48, 48, 0} };
+/* Penalties for one or more isolated pawns on a given file */
+static const int isolani_normal[8] = {
+ -8, -10, -12, -14, -14, -12, -10, -8
+};
+/* Penalties if the file is half-open (i.e. no enemy pawns on it) */
+static const int isolani_weaker[8] = {
+ -22, -24, -26, -28, -28, -26, -24, -22
+};
+
+static const BitBoard d2e2[2] =
+ { ULL(0x0018000000000000), ULL(0x0000000000001800) };
+static const BitBoard brank7[2] = { ULL(0x000000000000FF00),
+ ULL(0x00FF000000000000) };
+static const BitBoard brank8[2] = { ULL(0x00000000000000FF),
+ ULL(0xFF00000000000000) };
+static const BitBoard brank67[2] = { ULL(0x0000000000FFFF00),
+ ULL(0x00FFFF0000000000) };
+static const BitBoard brank58[2] = { ULL(0x00000000FFFFFFFF),
+ ULL(0xFFFFFFFF00000000) };
+
+int ScoreP (short side)
+/***************************************************************************
+ *
+ * Pawn evaluation is based on the following factors (which is being
+ * constantly updated!).
+ *
+ * 1. Pawn square tables.
+ * 2. Passed pawns.
+ * 3. Backward pawns.
+ * 4. Pawn base under attack.
+ * 5. Doubled pawns
+ * 6. Isolated pawns
+ * 7. Connected passed pawns on 6/7th rank.
+ * 8. Unmoved & blocked d, e pawn
+ * 9. Passed pawn which cannot be caught.
+ * 10. Pawn storms.
+ *
+ ***************************************************************************/
+{
+ int xside;
+ int s, sq, i, i1;
+ int n1, n2, backward;
+ int nfile[8];
+ int EnemyKing;
+ BitBoard c, t, p, blocker, *e;
+ PawnSlot *ptable;
+
+ if (board.b[side][pawn] == NULLBITBOARD)
+ return (0);
+ xside = 1^side;
+ EnemyKing = board.king[xside];
+ p = board.b[xside][pawn];
+ c = t = board.b[side][pawn];
+ ptable = PawnTab[side] + (PawnHashKey & PHashMask);
+ TotalPawnHashCnt++;
+ if (ptable->phase == phase && ptable->pkey == KEY(PawnHashKey))
+ {
+ GoodPawnHashCnt++;
+ s = ptable->score;
+ passed[side] = ptable->passed;
+ weaked[side] = ptable->weaked;
+ goto phase2;
+ }
+
+ s = 0;
+ passed[side] = NULLBITBOARD;
+ weaked[side] = NULLBITBOARD;
+ memset (nfile, 0, sizeof (nfile));
+ while (t)
+ {
+ sq = leadz (t);
+ CLEARBIT (t, sq);
+ s += PawnSq[side][sq];
+
+ /* Passed pawns */
+ if ((p & PassedPawnMask[side][sq]) == NULLBITBOARD)
+ {
+ if ((side == white && (FromToRay[sq][sq|56] & c) == 0) ||
+ (side == black && (FromToRay[sq][sq&7] & c) == 0))
+ {
+ passed[side] |= BitPosArray[sq];
+ s += (Passed[side][RANK(sq)] * phase) / 12;
+ }
+ }
+
+ /* Backward pawns */
+ backward = false;
+ /* i = sq + (side == white ? 8 : -8); */
+ if ( side == white ) {
+ i = sq + 8; }
+ else {
+ i= sq - 8; }
+
+ if (!(PassedPawnMask[xside][i] & ~FileBit[ROW(sq)] & c) &&
+ cboard[i] != pawn)
+ {
+ n1 = nbits (c & MoveArray[ptype[xside]][i]);
+ n2 = nbits (p & MoveArray[ptype[side]][i]);
+ if (n1 < n2)
+ backward = true;
+ }
+ if (!backward && (BitPosArray[sq] & brank7[xside]))
+ {
+ i1 = 1;
+ i = i + (side == white ? 8 : -8);
+ if (!(PassedPawnMask[xside][i] & ~FileBit[ROW(i1)] & c))
+ {
+ n1 = nbits (c & MoveArray[ptype[xside]][i]);
+ n2 = nbits (p & MoveArray[ptype[side]][i]);
+ if (n1 < n2)
+ backward = true;
+ }
+ }
+ if (backward)
+ {
+ weaked[side] |= BitPosArray[sq];
+ s += BACKWARDPAWN;
+ }
+
+ /* Pawn base under attack */
+ if ((MoveArray[ptype[side]][sq] & p) && (MoveArray[ptype[side]][sq] & c))
+ s += PAWNBASEATAK;
+
+ /* Increment file count for isolani & doubled pawn evaluation */
+ nfile[ROW(sq)]++;
+ }
+
+ for (i = 0; i <= 7; i++)
+ {
+ /* Doubled pawns */
+ if (nfile[i] > 1)
+ s += DOUBLEDPAWN;
+
+ /* Isolated pawns */
+ if (nfile[i] && (!(c & IsolaniMask[i])))
+ {
+ /* Isolated on a half-open file */
+ if (!(FileBit[i] & board.b[xside][pawn]))
+ s += isolani_weaker[i] * nfile[i];
+ else /* Normal isolated pawn */
+ s += isolani_normal[i] * nfile[i];
+ weaked[side] |= (c & FileBit[i]);
+ }
+ }
+
+
+ if (computerplays == side) {
+
+ /* Penalize having eight pawns */
+ if (nbits(board.b[computerplays][pawn]) == 8)
+ s += EIGHT_PAWNS;
+
+ /* Detect stonewall formation in enemy */
+ if (nbits(stonewall[xside] & board.b[xside][pawn]) == 3)
+ s += STONEWALL;
+
+ /* Locked pawns */
+ n = 0;
+ if (side == white)
+ n = nbits((c >> 8) & board.b[xside][pawn] &
+ boxes[1]);
+ else
+ n = nbits((c << 8) & board.b[xside][pawn] &
+ boxes[1]);
+ if (n > 1)
+ s += n * LOCKEDPAWNS;
+ }
+
+
+ /* Save the score into the pawn hash table */
+ ptable->pkey = KEY(PawnHashKey);
+ ptable->passed = passed[side];
+ ptable->weaked = weaked[side];
+ ptable->score = s;
+ ptable->phase = phase;
+
+/***************************************************************************
+ *
+ * This section of the pawn code cannot be saved into the pawn hash as
+ * they depend on the position of other pieces. So they have to be
+ * calculated again.
+ *
+ ***************************************************************************/
+phase2:
+
+ /* Pawn on f6/c6 with Queen against castled king is very strong */
+ c = board.b[side][pawn];
+ sq = board.king[xside];
+ if (side == white && board.b[side][queen] &&
+ (BitPosArray[C6] | BitPosArray[F6]) & c)
+ {
+ if (c & BitPosArray[F6] && sq > H6 && distance[sq][G7]==1)
+ s += PAWNNEARKING;
+ if (c & BitPosArray[C6] && sq > H6 && distance[sq][B7]==1)
+ s += PAWNNEARKING;
+ }
+ else if (side == black && board.b[side][queen] &&
+ (BitPosArray[C3] | BitPosArray[F3]) & c)
+ {
+ if (c & BitPosArray[F3] && sq < A3 && distance[sq][G2]==1)
+ s += PAWNNEARKING;
+ if (c & BitPosArray[C3] && sq < A3 && distance[sq][B2]==1)
+ s += PAWNNEARKING;
+ }
+
+ /* Connected passed pawns on 6th or 7th rank */
+ t = passed[side] & brank67[side];
+ if (t && (board.pmaterial[xside] == ValueR ||
+ (board.pmaterial[xside] == ValueN &&
+ pieces[xside] == board.b[xside][knight])))
+ {
+ n1 = ROW(board.king[xside]);
+ n2 = RANK(board.king[xside]);
+ for (i = 0; i <= 6; i++)
+ {
+ if (t & FileBit[i] && t & FileBit[i+1] && (n1 < i-1 || n1 > i+1 ||
+ (side == white && n2 < 4) || (side == black && n2 > 3)))
+ s += CONNECTEDPP;
+ }
+ }
+
+ /* Pawn on d2,e2/d7,e7 is blocked */
+ blocker = board.friends[side] | board.friends[xside];
+ if (side == white && (((c & d2e2[white]) >> 8) & blocker))
+ s += BLOCKDEPAWN;
+ if (side == black && (((c & d2e2[black]) << 8) & blocker))
+ s += BLOCKDEPAWN;
+
+ /* Enemy has no pieces & King is outside of passed pawn square */
+ if (passed[side] && board.pmaterial[xside]==0)
+ {
+ e = board.b[xside];
+ i1 = board.king[xside];
+ p = passed[side];
+ while (p)
+ {
+ sq = leadz (p);
+ CLEARBIT (p, sq);
+ if (board.side == side)
+ {
+ if (!(SquarePawnMask[side][sq] & board.b[xside][king]))
+ s += ValueQ * Passed[side][RANK(sq)] / PFACTOR;
+ }
+ else if (!(MoveArray[king][i1] & SquarePawnMask[side][sq]))
+ s += ValueQ * Passed[side][RANK(sq)] / PFACTOR;
+ }
+ }
+
+ /* If both sides are castled on different sides, bonus for pawn storms */
+ c = board.b[side][pawn];
+ if (abs (ROW (board.king[side]) - ROW (board.king[xside])) >= 4 &&
+ PHASE < 6)
+ {
+ n1 = ROW (board.king[xside]);
+ p = (IsolaniMask[n1] | FileBit[n1]) & c;
+ while (p)
+ {
+ sq = leadz (p);
+ CLEARBIT (p, sq);
+ s += 10 * (5 - distance[sq][board.king[xside]]);
+ }
+ }
+
+ return (s);
+}
+
+static const int Outpost[2][64] =
+{
+ { 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, 1, 1, 1, 1, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 1, 1, 1, 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 }
+};
+
+
+static inline int CTL(short sq, short piece __attribute__ ((unused)), short side)
+/***************************************************************************
+ *
+ * Return a score corresponding to the number of squares in the bitboard
+ * target multiplied by a specified bonus for controlling each square.
+ *
+ * Can be used for control of the center and attacks around the king.
+ *
+ ***************************************************************************/
+{
+ int s, n, EnemyKing, FriendlyKing;
+ BitBoard controlled;
+
+ s = 0;
+
+ EnemyKing = board.king[1^side];
+ FriendlyKing = board.king[side];
+
+ controlled = AttackXFrom (sq, side);
+
+ /* Center control */
+ n = nbits (controlled & boxes[0]);
+ s += 4*n;
+
+ /* Attacks against enemy king */
+ n = nbits (controlled & DistMap[EnemyKing][2]);
+ s += n;
+
+ /* Defenses for friendly king */
+ n = nbits (controlled & DistMap[FriendlyKing][2]);
+ s += n;
+
+ /* Mobility */
+ n = nbits(controlled);
+ s += 4*n;
+
+ return (s);
+}
+
+int ScoreN (short side)
+/***************************************************************************
+ *
+ * 1. central knight - distance from enemy king.
+ * 2. mobility/control/attack
+ * 3. outpost knight protected by pawn.
+ * 4. knight attacking weak pawns.
+ *
+ ***************************************************************************/
+{
+ int xside;
+ int s, s1, sq;
+ int EnemyKing;
+ BitBoard c, t;
+
+ if (board.b[side][knight] == NULLBITBOARD)
+ return (0);
+ xside = side^1;
+ s = s1 = 0;
+ c = board.b[side][knight];
+ t = board.b[xside][pawn];
+ EnemyKing = board.king[xside];
+
+ if ( c & pinned )
+ {
+ s += PINNEDKNIGHT * nbits(c & pinned);
+ }
+
+ while (c)
+ {
+ sq = leadz (c);
+ CLEARBIT (c, sq);
+
+ /* Control */
+ s1 = CTL(sq,knight,side);
+
+ if ( (BitPosArray[sq] & rings[3]) != NULLBITBOARD)
+ s1 += KNIGHTONRIM;
+
+ if (Outpost[side][sq] &&
+ !(t & IsolaniMask[ROW(sq)] & PassedPawnMask[side][sq]) )
+ {
+ s1 += OUTPOSTKNIGHT;
+
+ /* Knight defended by own pawn */
+ if (MoveArray[ptype[xside]][sq] & board.b[side][pawn])
+ s1 += OUTPOSTKNIGHT;
+ }
+
+ /* Attack on weak opponent pawns */
+ if (MoveArray[knight][sq] & weaked[xside])
+ s1 += ATAKWEAKPAWN;
+
+ s += s1;
+ }
+
+ return (s);
+}
+
+
+int ScoreB (short side)
+/****************************************************************************
+ *
+ * 1. double bishops.
+ * 2. mobility/control/attack
+ * 3. outpost bishop
+ * 4. fianchetto bishop
+ * 5. Bishop pair
+ *
+ ****************************************************************************/
+{
+ int xside;
+ int s, s1, n, sq, EnemyKing;
+ BitBoard c, t;
+
+ if (board.b[side][bishop] == NULLBITBOARD)
+ return (0);
+ s = s1 = 0;
+ c = board.b[side][bishop];
+ xside = side ^ 1;
+ EnemyKing = board.king[xside];
+ n = 0;
+ t = board.b[xside][pawn];
+
+ if ( c & pinned )
+ {
+ s += PINNEDBISHOP * nbits(c & pinned);
+ }
+
+ while (c)
+ {
+ sq = leadz (c);
+ CLEARBIT (c, sq);
+ n++;
+
+ /* Control */
+ s1 = CTL(sq,bishop,side);
+
+ /* Outpost bishop */
+ if (Outpost[side][sq] &&
+ !(t & IsolaniMask[ROW(sq)] & PassedPawnMask[side][sq]))
+ {
+ s1 += OUTPOSTBISHOP;
+
+ /* Bishop defended by own pawn */
+ if (MoveArray[ptype[xside]][sq] & board.b[side][pawn])
+ s1 += OUTPOSTBISHOP;
+ }
+
+ /* Fianchetto bishop */
+ if (side == white)
+ {
+ if (board.king[side] >= F1 && board.king[side] <= H1 && sq == G2)
+ s1 += FIANCHETTO;
+ if (board.king[side] >= A1 && board.king[side] <= C1 && sq == B2)
+ s1 += FIANCHETTO;
+ }
+ else if (side == black)
+ {
+ if (board.king[side] >= F8 && board.king[side] <= H8 && sq == G7)
+ s1 += FIANCHETTO;
+ if (board.king[side] >= A8 && board.king[side] <= C8 && sq == B7)
+ s1 += FIANCHETTO;
+ }
+
+ /* Attack on weak opponent pawns */
+ if (BishopAttack(sq) & weaked[xside])
+ s1 += ATAKWEAKPAWN;
+
+ s += s1;
+ }
+
+ /* Doubled bishops */
+ if (n > 1)
+ s += DOUBLEDBISHOPS;
+
+ return (s);
+
+}
+
+
+int BishopTrapped (short side)
+/****************************************************************************
+ *
+ * Check for bishops trapped at A2/H2/A7/H7
+ *
+ ****************************************************************************/
+{
+ int s = 0;
+
+ /* Don't waste time */
+ if (board.b[side][bishop] == NULLBITBOARD)
+ return (0);
+
+ if (side == white)
+ {
+ if ((board.b[white][bishop] & BitPosArray[A7]) &&
+ (board.b[black][pawn] & BitPosArray[B6]) && SwapOff(MOVE(A7,B6)) < 0)
+ s += BISHOPTRAPPED;
+ if ((board.b[white][bishop] & BitPosArray[H7]) &&
+ (board.b[black][pawn] & BitPosArray[G6]) && SwapOff(MOVE(H7,G6)) < 0)
+ s += BISHOPTRAPPED;
+ }
+ else
+ {
+ if ((board.b[black][bishop] & BitPosArray[A2]) &&
+ (board.b[white][pawn] & BitPosArray[B3]) && SwapOff(MOVE(A2,B3)) < 0)
+ s += BISHOPTRAPPED;
+ if ((board.b[black][bishop] & BitPosArray[H2]) &&
+ (board.b[white][pawn] & BitPosArray[G3]) && SwapOff(MOVE(H2,G3)) < 0)
+ s += BISHOPTRAPPED;
+ }
+
+ return (s);
+}
+
+int ScoreR (short side)
+/****************************************************************************
+ *
+ * 1. rook on 7th rank and Enemy king on 8th rank or pawns on 7th rank.
+ * 2. rook on open/half-open file.
+ * 3. rook in front/behind passed pawns (pawn >= 5th rank)
+ *
+ ****************************************************************************/
+{
+ int s, s1, sq, xside, fyle, EnemyKing;
+ BitBoard c;
+
+ if (board.b[side][rook] == NULLBITBOARD)
+ return (0);
+ s = s1 = 0;
+ c = board.b[side][rook];
+ xside = side ^ 1;
+ EnemyKing = board.king[xside];
+
+ if ( c & pinned )
+ {
+ s += PINNEDROOK * nbits(c & pinned);
+ }
+
+ while (c)
+ {
+ sq = leadz (c);
+ CLEARBIT (c, sq);
+
+ /* Control */
+ s1 = CTL(sq,rook,side);
+
+ fyle = ROW(sq);
+ if (PHASE < 7)
+ {
+ if (!(board.b[side][pawn] & FileBit[fyle]))
+ {
+ if (fyle == 5 && ROW(board.king[xside])>=E_FILE)
+ s1 += ROOKLIBERATED;
+ s1 += ROOKHALFFILE;
+ if (!(board.b[xside][pawn] & FileBit[fyle]))
+ s1 += ROOKOPENFILE;
+ }
+ }
+
+ if (phase > 6 && (FileBit[fyle] & passed[white] & brank58[white]))
+ {
+ if (nbits (Ray[sq][7] & passed[white]) == 1)
+ s1 += ROOKBEHINDPP;
+ else if (Ray[sq][4] & passed[white])
+ s1 += ROOKINFRONTPP;
+ }
+ if (FileBit[fyle] & passed[black] & brank58[black])
+ {
+ if (nbits (Ray[sq][4] & passed[black]) == 1)
+ s1 += ROOKBEHINDPP;
+ else if (Ray[sq][7] & passed[black])
+ s1 += ROOKINFRONTPP;
+ }
+
+ /* Attack on weak opponent pawns */
+ if (RookAttack(sq) & weaked[xside])
+ s1 += ATAKWEAKPAWN;
+
+ /* Rook on 7th rank */
+ if (RANK (sq) == rank7[side] && (RANK (EnemyKing) == rank8[side] ||
+ board.b[xside][pawn] & RankBit[RANK(sq)]))
+ s1 += ROOK7RANK;
+
+ s += s1;
+ }
+
+ return (s);
+}
+
+int DoubleQR7 (short side)
+/***************************************************************************
+ *
+ * This code just check to see if there is a QQ or QR or RR combo on the
+ * 7th rank. This is very strong and given quite a big bonus. This
+ * routine is called by the lazy section.
+ *
+ ***************************************************************************/
+{
+ int xside;
+
+ xside = 1^side;
+ if (nbits ((board.b[side][queen]|board.b[side][rook]) & brank7[side]) > 1
+ && ((board.b[xside][king] & brank8[side]) ||
+ (board.b[xside][pawn] & brank7[side])))
+
+ return (ROOKS7RANK);
+ else
+ return (0);
+}
+
+int ScoreQ (short side)
+/***************************************************************************
+ *
+ * 1. queen centralization.
+ * 2. king tropism.
+ * 3. Bonus if opponent king is exposed.
+ *
+ ***************************************************************************/
+{
+ int xside;
+ int s, s1, sq, EnemyKing;
+ BitBoard c;
+
+ s = s1 = 0;
+
+ /* Try to keep our queen on the board for attacking purposes. */
+ if (board.b[side][queen] == NULLBITBOARD) {
+ if (side == computer) {
+ s += QUEEN_NOT_PRESENT;
+ }
+ return(s);
+ }
+
+ xside = 1 ^ side;
+ c = board.b[side][queen];
+ EnemyKing = board.king[xside];
+
+ if ( c & pinned )
+ {
+ s += PINNEDQUEEN * nbits(c & pinned);
+ }
+
+ while (c)
+ {
+ sq = leadz (c);
+ CLEARBIT (c, sq);
+
+ /* Control */
+ s1 = CTL(sq,queen,side);
+
+ if (distance[sq][EnemyKing] <= 2)
+ s1 += QUEENNEARKING;
+
+ /* Attack on weak opponent pawns */
+ if (QueenAttack(sq) & weaked[xside])
+ s1 += ATAKWEAKPAWN;
+
+ s += s1;
+ }
+
+ return (s);
+}
+
+
+static const int KingSq[64] =
+{
+ 24, 24, 24, 16, 16, 0, 32, 32,
+ 24, 20, 16, 12, 12, 16, 20, 24,
+ 16, 12, 8, 4, 4, 8, 12, 16,
+ 12, 8, 4, 0, 0, 4, 8, 12,
+ 12, 8, 4, 0, 0, 4, 8, 12,
+ 16, 12, 8, 4, 4, 8, 12, 16,
+ 24, 20, 16, 12, 12, 16, 20, 24,
+ 24, 24, 24, 16, 16, 0, 32, 32
+};
+
+static const int EndingKing[64] =
+{
+ 0, 6, 12, 18, 18, 12, 6, 0,
+ 6, 12, 18, 24, 24, 18, 12, 6,
+ 12, 18, 24, 32, 32, 24, 18, 12,
+ 18, 24, 32, 48, 48, 32, 24, 18,
+ 18, 24, 32, 48, 48, 32, 24, 18,
+ 12, 18, 24, 32, 32, 24, 18, 12,
+ 6, 12, 18, 24, 24, 18, 12, 6,
+ 0, 6, 12, 18, 18, 12, 6, 0
+};
+
+static const int pawncover[9] = { -60, -30, 0, 5, 30, 30, 30, 30, 30 };
+static const int factor[9] = { 7, 8, 8, 7, 6, 5, 4, 2, 0, };
+
+int ScoreK (short side)
+/***************************************************************************
+ *
+ * 1. king in the corner. ?? SRW 2002-08-02 Unclear if implemented
+ * 2. pawns around king.
+ * 3. king on open file.
+ * 4. Uncastled king.
+ * 5. Open rook file via Ng5 or Bxh7 sac.
+ * 6. No major or minor piece in the king's quadrant.
+ *
+ ***************************************************************************/
+{
+ int xside;
+ int s, sq, sq1, n, n1, n2, file, fsq, rank;
+ BitBoard b, x;
+
+ s = 0;
+ xside = 1^side;
+ sq = board.king[side];
+ file = ROW (sq);
+ rank = RANK (sq);
+ KingSafety[side] = 0;
+ if (!ENDING)
+ {
+
+ s += ((6 - phase) * KingSq[sq] + phase * EndingKing[sq]) / 6;
+
+ /* After castling kingside, reward having all 3 pawns in front but not if
+ there is a threatening pawn. This permits the freeing move F3/F6. */
+
+ if (side == white)
+ n = nbits (MoveArray[king][sq] & board.b[side][pawn] & RankBit[rank+1]);
+ else
+ n = nbits (MoveArray[king][sq] & board.b[side][pawn] & RankBit[rank-1]);
+ s += pawncover[n];
+
+ /* Penalize compromised wing pawn formations prior to castle. */
+ if (!board.castled[side]) {
+ n = -1;
+ if (side == white) {
+ /* King on original square and unmoved */
+ if (sq == 4 && Mvboard[sq] == 0) {
+ /* Kingside - rook on original square and unmoved. */
+ if ( (board.b[side][rook] & BitPosArray[H1])!=NULLBITBOARD &&
+ Mvboard[H1] == 0)
+ n = nbits (MoveArray[king][G1] &
+ board.b[side][pawn] & RankBit[rank+1]);
+ /* Queenside */
+ if ( (board.b[side][rook] & BitPosArray[A1])!=NULLBITBOARD &&
+ Mvboard[A1] == 0)
+ n = nbits (MoveArray[king][C1] &
+ board.b[side][pawn] & RankBit[rank+1]);
+ }
+ } else {
+ if (sq == 60 && Mvboard[sq] == 0) {
+ /* Kingside */
+ if ( (board.b[side][rook] & BitPosArray[H8])!=NULLBITBOARD &&
+ Mvboard[H8] == 0)
+ n = nbits (MoveArray[king][G8] &
+ board.b[side][pawn] & RankBit[rank-1]);
+ /* Queenside */
+ if ( (board.b[side][rook] & BitPosArray[A8])!=NULLBITBOARD &&
+ Mvboard[A8] == 0)
+ n = nbits (MoveArray[king][C8] &
+ board.b[side][pawn] & RankBit[rank-1]);
+ }
+ }
+
+ /* Penalize breaking the wing pawn formations prior to castle */
+ if (n != -1) s += pawncover[n];
+ }
+
+ if (side == computer && file >= F_FILE &&
+ !(FileBit[G_FILE] & board.b[side][pawn]))
+ {
+ if (side == white && cboard[F2] == pawn)
+ s += GOPEN;
+ else if (side == black && cboard[F7] == pawn)
+ s += GOPEN;
+ }
+
+ /* No friendly pawns on this king file */
+ if (!(FileBit[file] & board.b[side][pawn]))
+ s += KINGOPENFILE;
+
+ /* No enemy pawns on this king file */
+ if (!(FileBit[file] & board.b[xside][pawn]))
+ s += KINGOPENFILE1;
+
+ switch (file)
+ {
+ case A_FILE :
+ case E_FILE :
+ case F_FILE :
+ case G_FILE : if (!(FileBit[file+1] & board.b[side][pawn]))
+ s += KINGOPENFILE;
+ if (!(FileBit[file+1] & board.b[xside][pawn]))
+ s += KINGOPENFILE1;
+ break;
+ case H_FILE :
+ case D_FILE :
+ case C_FILE :
+ case B_FILE : if (!(FileBit[file-1] & board.b[side][pawn]))
+ s += KINGOPENFILE;
+ if (!(FileBit[file-1] & board.b[xside][pawn]))
+ s += KINGOPENFILE1;
+ break;
+ default :
+ break;
+ }
+
+ if (board.castled[side]) {
+ if (side == white) {
+ if (file > E_FILE) {
+ if (!(BitPosArray[F2] & board.b[side][pawn]) ||
+ !(BitPosArray[G2] & board.b[side][pawn]) ||
+ !(BitPosArray[H2] & board.b[side][pawn]) )
+ s += RUPTURE;
+ } else if (file < E_FILE) {
+ if (!(BitPosArray[A2] & board.b[side][pawn]) ||
+ !(BitPosArray[B2] & board.b[side][pawn]) ||
+ !(BitPosArray[C2] & board.b[side][pawn]) )
+ s += RUPTURE;
+ }
+ } else {
+ if (file > E_FILE) {
+ if (!(BitPosArray[F7] & board.b[side][pawn]) ||
+ !(BitPosArray[G7] & board.b[side][pawn]) ||
+ !(BitPosArray[H7] & board.b[side][pawn]) )
+ s += RUPTURE;
+ } else if (file < E_FILE) {
+ if (!(BitPosArray[A7] & board.b[side][pawn]) ||
+ !(BitPosArray[B7] & board.b[side][pawn]) ||
+ !(BitPosArray[C7] & board.b[side][pawn]) )
+ s += RUPTURE;
+ }
+ }
+ }
+ if (side == computer) {
+
+ /* Stock piece sacrifice on h file */
+
+ if (file >= E_FILE && board.b[xside][queen] && board.b[xside][rook] &&
+ !((board.b[side][pawn]|board.b[xside][pawn]) & FileBit[7]))
+ s += HOPEN;
+
+ /* King trapping rook */
+ if (side == white) {
+ if (file > E_FILE) {
+ if (board.b[side][rook]&mask_kr_trapped_w[H_FILE-file]) {
+ s += ROOKTRAPPED;
+ }
+ } else if (file < D_FILE) {
+ if (board.b[side][rook]&mask_qr_trapped_w[file]) {
+ s += ROOKTRAPPED;
+ }
+ }
+ } else {
+ if (file > E_FILE) {
+ if (board.b[side][rook]&mask_kr_trapped_b[H_FILE-file]) {
+ s += ROOKTRAPPED;
+ }
+ } else if (file < D_FILE) {
+ if (board.b[side][rook]&mask_qr_trapped_b[file]) {
+ s += ROOKTRAPPED;
+ }
+ }
+ }
+ }
+
+ /* Don't give fianchetto target for advanced pawns */
+ if (file > E_FILE && ROW(board.king[xside]) < D_FILE) {
+ if (side == white) fsq = G3; else fsq = G6;
+ if ((BitPosArray[fsq] & board.b[side][pawn]) != NULLBITBOARD)
+ if (((BitPosArray[F4]|BitPosArray[H4]|
+ BitPosArray[F5]|BitPosArray[H5])
+ & board.b[xside][pawn]) != NULLBITBOARD)
+ s += FIANCHETTO_TARGET;
+ }
+ if (file < E_FILE && ROW(board.king[xside]) > E_FILE) {
+ if (side == white) fsq = B3; else fsq = B6;
+ if ((BitPosArray[fsq] & board.b[side][pawn]) != NULLBITBOARD)
+ if (((BitPosArray[A4]|BitPosArray[C4]|
+ BitPosArray[A5]|BitPosArray[C5])
+ & board.b[xside][pawn]) != NULLBITBOARD)
+ s += FIANCHETTO_TARGET;
+ }
+
+ /* No major/minor piece in king's quadrant */
+ /* First identify the quadrant */
+ x = boardhalf[side] & boardside[file<=D_FILE];
+ /* Now identify the number of non-pawn enemy in quadrant */
+ n1 = nbits(x & (board.friends[xside]));
+ if (n1 > 0) {
+ /* Now identify the number of non-pawn friends in quadrant */
+ n2 = nbits(x & (board.friends[side] & ~board.b[side][pawn] &
+ ~board.b[side][king]));
+ if (n1 > n2)
+ s += (n1 - n2) * KING_DEFENDER_DEFICIT;
+ }
+
+ KingSafety[side] = s;
+ s = (s * factor[phase]) / 8;
+ }
+ else
+ {
+ s += EndingKing[sq];
+ s += CTL(sq,king,side);
+ b = (board.b[white][pawn] | board.b[black][pawn]);
+ while (b)
+ {
+ sq1 = leadz (b);
+ CLEARBIT (b, sq1);
+ if (BitPosArray[sq1] & board.b[white][pawn])
+ s -= distance[sq][sq1+8] * 10 - 5;
+ else if (BitPosArray[sq1] & board.b[white][pawn])
+ s -= distance[sq][sq1-8] * 10 - 5;
+ else
+ s -= distance[sq][sq1] - 5;
+ }
+
+ /* Attack on weak opponent pawns */
+ if (MoveArray[king][sq] & weaked[xside])
+ s += ATAKWEAKPAWN * 2;
+
+ }
+
+ if (phase >= 4) {
+ /* Weak back rank */
+ if (side == white) {
+ if (sq < A2)
+ if (!(MoveArray[king][sq] & (~board.b[side][pawn] & RankBit[1])))
+ s += KING_BACK_RANK_WEAK;
+ } else {
+ if (sq > H7)
+ if (!(MoveArray[king][sq] & (~board.b[side][pawn] & RankBit[6])))
+ s += KING_BACK_RANK_WEAK;
+ }
+ }
+
+ return (s);
+}
+
+
+int LoneKing (int side, int loser)
+/**************************************************************************
+ *
+ * One side has a lonely king and the other has no pawns, but enough
+ * mating material. We give an additional bonus of 150 points for the
+ * winning side to attract the search to such positions.
+ *
+ **************************************************************************/
+{
+ int s, winer, sq1, sq2;
+
+ winer = 1^loser;
+ if (board.material[winer] == ValueB+ValueN &&
+ nbits(board.b[winer][bishop]) == 1 &&
+ nbits(board.b[winer][knight]) == 1)
+ return (ScoreKBNK (side, loser));
+
+ sq1 = board.king[winer];
+ sq2 = board.king[loser];
+ s = 150 - 6 * taxicab[sq1][sq2] - EndingKing[sq2];
+ if (side == loser)
+ s = -s;
+ s += MATERIAL;
+
+ return (s);
+}
+
+
+int KPK (int side)
+/**************************************************************************
+ *
+ * A KPK endgame evaluator. Side is the one on the move.
+ * This is not a perfect evaluator, it merely identifies SOME positions
+ * as wins or draw. Some WON positions could be seen as draws; the search
+ * will be able to use the knowledge here to identify more positions.
+ *
+ **************************************************************************/
+{
+ int winer, loser, sq, sqw, sql;
+ int s;
+
+ winer = (board.b[white][pawn] ? white : black);
+ loser = 1 ^ winer;
+ sq = leadz (board.b[winer][pawn]);
+ sqw = board.king[winer];
+ sql = board.king[loser];
+ s = ValueP + (ValueQ * Passed[winer][RANK(sq)] / PFACTOR) +
+ 4 * (winer == white ? RANK(sqw) : 7-RANK(sqw));
+
+/**************************************************************************
+ *
+ * Pawn is outside the square of the king
+ *
+ **************************************************************************/
+ if (~SquarePawnMask[winer][sq] & board.b[loser][king])
+ {
+ if (!(MoveArray[king][sql] & SquarePawnMask[winer][sq]))
+ return (winer == side ? s : -s);
+ if (winer == side)
+ return (s);
+ }
+
+/**************************************************************************
+ *
+ * Friendly king is on same or adjacent file to the pawn, and the pawn is
+ * on a file other than a rook file and ...
+ *
+ **************************************************************************/
+ if (ROW(sq) != 0 && ROW(sq) != 7 &&
+ ((IsolaniMask[ROW(sq)] | FileBit[ROW(sq)]) & board.b[winer][king]))
+ {
+
+/**************************************************************************
+ *
+ * a. friendly king is 2 ranks more advanced than the pawn
+ * b. friendly king is 1 rank more advanced than the pawn
+ * i. The friendly king is on the sixth rank.
+ * ii. The enemy king does not have direct opposition by being 2 ranks
+ * in front of the friendly king and on the same file.
+ * c. friendly king is same rank as pawn
+ * i. The enemy king is not 2-4 ranks more advanced that the pawn.
+ * ii. The pawn is on the sixth rank and the enemy king does not have
+ * direct opposition.
+ * d. pawn is on the 7th rank, friendly king is on sixth rank and
+ * i. The enemy king is not on the queening square.
+ * ii. The enemy is on the queening square but both kings are in the same
+ * file.
+ *
+ **************************************************************************/
+ if (winer == white)
+ {
+ if (RANK(sqw) == RANK(sq) + 2)
+ return (winer == side ? s : -s);
+ if (RANK(sqw) == RANK(sq) + 1)
+ {
+ if (RANK(sqw) == 5)
+ return (winer == side ? s : -s);
+ if (sqw < A6)
+ {
+ if (sqw+16 == sql && winer == side)
+ return (0);
+ else
+ return (winer == side ? s : -s);
+ }
+ }
+ if (RANK(sqw) == RANK(sq))
+ {
+ if ((RANK(sql) - RANK(sq) < 2 || RANK(sql) - RANK(sq) > 4) &&
+ winer == side)
+ return (s);
+ if ((RANK(sql) - RANK(sq) < 1 || RANK(sql) - RANK(sq) > 5) &&
+ loser == side)
+ return (-s);
+ if (RANK(sq) == 5 && sqw+16 != sql)
+ return (winer == side ? s : 0);
+ }
+ if (RANK(sq) == 6 && RANK(sqw) == 5)
+ {
+ if (sql != sq+8)
+ return (winer == side ? s : 0);
+ if (sql == sq+8 && sql == sqw+16)
+ return (winer == side ? s : 0);
+ }
+ }
+ else
+ {
+ if (RANK(sqw) == RANK(sq) - 2)
+ return (winer == side ? s : -s);
+ if (RANK(sqw) == RANK(sq) - 1)
+ {
+ if (RANK(sqw) == 2)
+ return (winer == side ? s : -s);
+ if (sqw > H3)
+ {
+ if (sqw-16 == sql && winer == side)
+ return (0);
+ else
+ return (winer == side ? s : -s);
+ }
+ }
+ if (RANK(sqw) == RANK(sq))
+ {
+ if ((RANK(sq) - RANK(sql) < 2 || RANK(sq) - RANK(sql) > 4) &&
+ winer == side)
+ return (s);
+ if ((RANK(sq) - RANK(sql) < 1 || RANK(sq) - RANK(sql) > 5) &&
+ loser == side)
+ return (-s);
+ if (RANK(sq) == 5 && sqw+16 != sql)
+ return (winer == side ? s : 0);
+ }
+ if (RANK(sq) == 1 && RANK(sqw) == 2)
+ {
+ if (sql != sq-8)
+ return (winer == side ? s : 0);
+ if (sql == sq-8 && sql == sqw-16)
+ return (winer == side ? s : 0);
+ }
+ }
+ }
+
+ return (0);
+}
+
+
+int KBNK[64] =
+{
+ 0, 10, 20, 30, 40, 50, 60, 70,
+ 10, 20, 30, 40, 50, 60, 70, 60,
+ 20, 30, 40, 50, 60, 70, 60, 50,
+ 30, 40, 50, 60, 70, 60, 50, 40,
+ 40, 50, 60, 70, 60, 50, 40, 30,
+ 50, 60, 70, 60, 50, 40, 30, 20,
+ 60, 70, 60, 50, 40, 30, 20, 10,
+ 70, 60, 50, 40, 30, 20, 10, 0
+};
+
+int ScoreKBNK (int side, int loser)
+/****************************************************************************
+ *
+ * My very own KBNK routine!
+ *
+ ****************************************************************************/
+{
+ int s, winer, sq1, sq2, sqB;
+
+ winer = 1^loser;
+ sqB = board.king[loser];
+ if (board.b[winer][bishop] & WHITESQUARES)
+ sqB = RANK(sqB)*8 + 7 - ROW(sqB);
+ sq1 = board.king[winer];
+ sq2 = board.king[loser];
+ s = 300 - 6 * taxicab[sq1][sq2];
+ s -= KBNK[sqB];
+ s -= EndingKing[sq2];
+ s -= taxicab[leadz(board.b[winer][knight])][sq2];
+ s -= taxicab[leadz(board.b[winer][bishop])][sq2];
+
+ /* King in the central 4x4 region is good! */
+ if (board.b[winer][king] & ULL(0x00003C3C3C3C0000))
+ s += 20;
+ if (side == loser)
+ s = -s;
+ s += MATERIAL;
+
+ return (s);
+}
+
+
+static const BitBoard nn[2] = { ULL(0x4200000000000000), ULL(0x0000000000000042) };
+static const BitBoard bb[2] = { ULL(0x2400000000000000), ULL(0x0000000000000024) };
+
+int ScoreDev (short side)
+/***************************************************************************
+ *
+ * Calculate the development score for side (for opening only).
+ * Penalize the following.
+ * . Uncastled and cannot castled
+ * . Undeveloped knights and bishops
+ * . Early queen move.
+ *
+ ***************************************************************************/
+{
+ int s;
+ int sq;
+ BitBoard c;
+
+ /* Calculate whether we are developed */
+ c = (board.b[side][knight] & nn[side]) | (board.b[side][bishop] & bb[side]);
+ s = nbits(c) * -8;
+
+ /* If we are castled or beyond the 20th move, no more ScoreDev */
+ if (board.castled[side] || GameCnt >= 38)
+ return (s);
+
+ s += NOTCASTLED;
+
+ /* If the king is moved, nail it, otherwise check rooks */
+ if (Mvboard[board.king[side]] > 0)
+ s += KINGMOVED;
+
+ /* Discourage rook moves */
+ c = board.b[side][rook];
+ while (c) {
+ sq = leadz(c);
+ CLEARBIT(c, sq);
+ if (Mvboard[sq] > 0)
+ s += ROOKMOVED;
+ }
+
+ /* Penalize a queen that moves at all */
+ if (board.b[side][queen])
+ {
+ sq = leadz (board.b[side][queen]);
+ if (Mvboard[sq] > 0)
+ s += EARLYQUEENMOVE;
+ /* s += Mvboard[sq] * EARLYQUEENMOVE; */
+ }
+
+ /* Discourage repeat minor piece moves */
+ c = board.b[side][knight] | board.b[side][bishop];
+ while (c) {
+ sq = leadz(c);
+ CLEARBIT(c, sq);
+ if (Mvboard[sq] > 1)
+ s += EARLYMINORREPEAT;
+ /* s += Mvboard[sq] * EARLYMINORREPEAT; */
+ }
+
+ /* Discourage any wing pawn moves */
+/* c = board.b[side][pawn] & (FileBit[0]|FileBit[1]|FileBit[6]|FileBit[7]); */
+ c = board.b[side][pawn] & ULL(0xc3c3c3c3c3c3c3c3);
+ while (c) {
+ sq = leadz(c);
+ CLEARBIT(c, sq);
+ if (Mvboard[sq] > 0)
+ s += EARLYWINGPAWNMOVE;
+ }
+
+ /* Discourage any repeat center pawn moves */
+/* c = board.b[side][pawn] & (FileBit[2]|FileBit[3]|FileBit[4]|FileBit[5]); */
+ c = board.b[side][pawn] & ULL(0x3c3c3c3c3c3c3c3c);
+ while (c) {
+ sq = leadz(c);
+ CLEARBIT(c, sq);
+ if (Mvboard[sq] > 1)
+ s += EARLYCENTERPREPEAT;
+ }
+
+ return (s);
+}
+
+
+/* Array of pointer to functions */
+static int (*ScorePiece[7]) (short) =
+{ NULL, ScoreP, ScoreN, ScoreB, ScoreR, ScoreQ, ScoreK };
+
+
+int Evaluate (int alpha, int beta)
+/****************************************************************************
+ *
+ * First check to see if this position can be specially dealt with.
+ * E.g. if our bounds indicate that we are looking for a mate score,
+ * then just return the material score. Nothing else is important.
+ * If its a KPK endgame, call our KPK routine.
+ * If one side has a lone king & the winning side has no pawns then call
+ * the LoneKing() mating driver routine. Note that there is enough
+ * mating material as we have already check for insufficient mating material
+ * in the call to EvaluateDraw() in search()/quiesce().
+ *
+ ****************************************************************************/
+{
+ int side, xside;
+ int piece, s, s1, score;
+ int npiece[2];
+ BitBoard *b;
+
+ side = board.side;
+ xside = 1 ^ side;
+
+ /* If we are looking for a MATE, just return the material */
+ if (alpha > MATE-255 || beta < -MATE+255)
+ return (MATERIAL);
+
+ /* A KPK endgame. */
+ if (board.material[white]+board.material[black] == ValueP)
+ return (KPK (side));
+
+ /* One side has a lone king and other side has no pawns */
+ if (board.material[xside] == 0 && board.b[side][pawn] == NULLBITBOARD)
+ return LoneKing (side, xside);
+ if (board.material[side] == 0 && board.b[xside][pawn] == NULLBITBOARD)
+ return LoneKing (side, side);
+
+/****************************************************************************
+ *
+ * Lets try a lazy evaluation. In this stage, we should evaluate all those
+ * features that gives big bonus/penalties. E.g. squares around king is
+ * attacked by enemy pieces, 2 rooks on 7th rank, runaway passed pawns etc.
+ * This will be the direction, so things will continue to change in this
+ * section.
+ *
+ ****************************************************************************/
+ EvalCall++;
+ phase = PHASE;
+ b = board.b[white];
+ pieces[white] = b[knight] | b[bishop] | b[rook] | b[queen];
+ npiece[white] = nbits (pieces[white]);
+ b = board.b[black];
+ pieces[black] = b[knight] | b[bishop] | b[rook] | b[queen];
+ npiece[black] = nbits (pieces[black]);
+ s1 = MATERIAL;
+
+ if ((s1 + maxposnscore[side] < alpha || s1 - maxposnscore[xside] > beta) &&
+ phase <= 6)
+ {
+ score = s1;
+ goto next;
+ }
+ s = 0;
+ s += ScoreDev (side) - ScoreDev (xside);
+ s += ScoreP (side) - ScoreP (xside);
+ s += ScoreK (side) - ScoreK (xside);
+ s += BishopTrapped (side) - BishopTrapped (xside);
+ s += DoubleQR7 (side) - DoubleQR7 (xside);
+
+ s1 = s + MATERIAL;
+
+/**************************************************************************
+ *
+ * See if we can have a lazy evaluation cut. Otherwise its a slow eval.
+ *
+ **************************************************************************/
+
+ if (s1 + lazyscore[side] < alpha || s1 - lazyscore[side] > beta)
+ {
+ score = s1;
+ }
+ else
+ {
+ EvalCnt++;
+
+ GenAtaks();
+ s1 = HUNGPENALTY * ( EvalHung(side) - EvalHung(xside) );
+ FindPins(&pinned);
+
+ for (piece = knight; piece < king; piece++)
+ {
+ s1 += (*ScorePiece[piece]) (side) - (*ScorePiece[piece]) (xside);
+ }
+ lazyscore[side] = MAX (s1, lazyscore[side]);
+ maxposnscore[side] = MAX (maxposnscore[side], s + s1);
+ score = s + s1 + MATERIAL;
+ }
+
+/***************************************************************************
+ *
+ * Trade down bonus code. When ahead, trade pieces & not pawns;
+ *
+ ***************************************************************************/
+next:
+ if (MATERIAL >= 200)
+ {
+ score += (RootPieces - nbits(pieces[white] | pieces[black])) * TRADEPIECE;
+ score -= (RootPawns - nbits(board.b[white][pawn] | board.b[black][pawn]))
+ * TRADEPAWNS;
+ }
+ else if (MATERIAL <= -200)
+ {
+ score -= (RootPieces - nbits(pieces[white] | pieces[black])) * TRADEPIECE;
+ score += (RootPawns - nbits(board.b[white][pawn] | board.b[black][pawn]))
+ * TRADEPAWNS;
+ }
+
+/***************************************************************************
+ *
+ * Opposite color bishops is drawish.
+ *
+ ***************************************************************************/
+ if (ENDING && pieces[white] == board.b[white][bishop] &&
+ pieces[black] == board.b[black][bishop] &&
+ ((pieces[white] & WHITESQUARES && pieces[black] & BLACKSQUARES) ||
+ (pieces[white] & BLACKSQUARES && pieces[black] & WHITESQUARES)))
+ {
+ score /= 2;
+ }
+
+/***************************************************************************
+ *
+ * When one side has no mating material, then his score can never be > 0.
+ *
+ ***************************************************************************/
+ if (score > 0 && !board.b[side][pawn] && (board.material[side] < ValueR
+ || pieces[side] == board.b[side][knight]))
+ score = 0;
+ if (score < 0 && !board.b[xside][pawn] && (board.material[xside] < ValueR
+ || pieces[xside] == board.b[xside][knight]))
+ score = 0;
+
+ return (score);
+}
+
+
+short EvaluateDraw (void)
+/***************************************************************************
+ *
+ * This routine is called by search() and quiesce() before anything else
+ * is done. Its purpose it to check if the current position is a draw.
+ * 0. 50-move draw.
+ * 1. If there are any pawns, it is not.
+ * 2. If both sides has anything less than a rook, draw.
+ * 3. If both sides has <= 2 knights only, draw.
+ * 4. If its a KBBK and bishops of same color, draw.
+ *
+ ***************************************************************************/
+{
+ BitBoard *w, *b;
+ int wm, bm, wn, bn;
+
+ /*
+ * Exception - if we are close to a pawn move, promotion
+ * or capture it is possible a forced mate will follow.
+ * So we assume not drawn for 2 moves.
+ */
+
+ if ( (GameCnt-Game50) < 5 )
+ return (false);
+
+ /* 50 move rule */
+ if ( (GameCnt-Game50) > 100 )
+ return (true);
+
+ w = board.b[white];
+ b = board.b[black];
+ if (w[pawn] != 0 || b[pawn] != 0)
+ return (false);
+
+ wm = board.material[white];
+ bm = board.material[black];
+ wn = nbits (w[knight]);
+ bn = nbits (b[knight]);
+ if ((wm<ValueR || (wm==2*ValueN && wn==2)) &&
+ (bm<ValueR || (bm==2*ValueN && bn==2)))
+ return (true);
+
+ if (wm < ValueR)
+ {
+ if (bm == 2*ValueB &&
+ ( nbits(board.b[black][bishop] & WHITESQUARES) == 2 ||
+ nbits(board.b[black][bishop] & BLACKSQUARES) == 2 ))
+ return (true);
+ }
+ if (bm < ValueR)
+ {
+ if (wm == 2*ValueB &&
+ ( nbits(board.b[white][bishop] & WHITESQUARES) == 2 ||
+ nbits(board.b[white][bishop] & BLACKSQUARES) == 2 ))
+ return (true);
+ }
+
+ return (false);
+}
diff --git a/src/chess_computer-activity/gnuchess/eval.h b/src/chess_computer-activity/gnuchess/eval.h
new file mode 100644
index 0000000..8520551
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/eval.h
@@ -0,0 +1,118 @@
+/* GNU Chess 5.0 - eval.h - evaluation symbolic definitions
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#ifndef EVAL_H
+#define EVAL_H
+
+/****************************************************************************
+ *
+ * The various evaluations constants.
+ *
+ ****************************************************************************/
+
+#define OPENING (phase <= 2)
+#define ENDING (phase >= 6)
+#define TRADEPIECE 4
+#define TRADEPAWNS 8
+#define HUNGPENALTY -20
+#define ROOKMOVED -20
+#define KINGMOVED -20
+#define NOTCASTLED -8
+#define PFACTOR 550
+#define EARLYMINORREPEAT -7
+
+/***********/
+/* Pawns */
+/***********/
+#define EIGHT_PAWNS -10
+#define STONEWALL -10
+#define LOCKEDPAWNS -10
+#define EARLYWINGPAWNMOVE -6
+#define EARLYCENTERPREPEAT -6
+#define BACKWARDPAWN -(8+phase)
+#define DOUBLEDPAWN -(8+phase)
+#define PAWNBASEATAK -18
+#define BLOCKDEPAWN -48 /* -12 */
+#define CONNECTEDPP 50
+#define PAWNNEARKING 40
+#define ATAKWEAKPAWN 2
+#define FIANCHETTO_TARGET -13
+
+
+/*************/
+/* Knights */
+/*************/
+#define KNIGHTONRIM -13
+#define OUTPOSTKNIGHT 10
+#define PINNEDKNIGHT -30
+#define KNIGHTTRAPPED -250
+
+
+/*************/
+/* Bishops */
+/*************/
+#define DOUBLEDBISHOPS 18
+#define OUTPOSTBISHOP 8
+#define FIANCHETTO 8
+#define GOODENDINGBISHOP 16
+#define BISHOPTRAPPED -250
+#define PINNEDBISHOP -30
+
+/***********/
+/* Rooks */
+/***********/
+#define ROOK7RANK 30
+#define ROOKS7RANK 30
+#define ROOKHALFFILE 5
+#define ROOKOPENFILE 6
+#define ROOKBEHINDPP 6
+#define ROOKINFRONTPP -10
+#define PINNEDROOK -50
+#define ROOKTRAPPED -10
+#define ROOKLIBERATED 40
+
+/***********/
+/* Queen */
+/***********/
+#define EARLYQUEENMOVE -40
+#define QUEENNEARKING 12
+#define PINNEDQUEEN -90
+#define QUEEN_NOT_PRESENT -25
+
+/**********/
+/* King */
+/**********/
+#define KINGOPENFILE -10
+#define KINGOPENFILE1 -6
+#define ATAKKING 10
+#define DEFENDKING 6
+#define HOPEN -600
+#define GOPEN -30
+#define KING_DEFENDER_DEFICIT -50
+#define KING_BACK_RANK_WEAK -40
+#define RUPTURE -20
+
+#endif /* !EVAL_H */
diff --git a/src/chess_computer-activity/gnuchess/genmove.c b/src/chess_computer-activity/gnuchess/genmove.c
new file mode 100644
index 0000000..69f2f7c
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/genmove.c
@@ -0,0 +1,788 @@
+/* GNU Chess 5.0 - genmove.c - move generator code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+
+#include "common.h"
+
+const short raybeg[7] = { 0, 0, 0, 0, 4, 0, 0 };
+const short rayend[7] = { 0, 0, 0, 4, 8, 8, 0 };
+
+static leaf *node;
+
+#define ADDMOVE(a,b,c) \
+ do { \
+ node->move = MOVE(a,b) | (c); \
+ node++; \
+ } while (0)
+
+#define ADDPROMOTE(a,b) \
+ do { \
+ ADDMOVE (a, b, QUEENPRM); \
+ ADDMOVE (a, b, KNIGHTPRM); \
+ ADDMOVE (a, b, ROOKPRM); \
+ ADDMOVE (a, b, BISHOPPRM); \
+ } while (0)
+
+static inline void BitToMove (short f, BitBoard b)
+/***************************************************************************
+ *
+ * Convert a bitboard into a list of moves. These are stored
+ * into the tree. f is the origin square.
+ *
+ ***************************************************************************/
+{
+ int t;
+
+ while (b)
+ {
+ t = leadz (b);
+ CLEARBIT (b, t);
+ ADDMOVE (f, t, 0);
+ }
+}
+
+
+
+void GenMoves (short ply)
+/****************************************************************************
+ *
+ * My bitboard move generator. Let's see how fast we can go!
+ * This routine generates pseudo-legal moves.
+ *
+ ****************************************************************************/
+{
+ int side;
+ int piece, sq, t, ep;
+ BitBoard b, c, d, e, friends, notfriends, blocker, notblocker;
+ BitBoard *a;
+
+ side = board.side;
+ a = board.b[side];
+ friends = board.friends[side];
+ notfriends = ~friends;
+ blocker = board.blocker;
+ notblocker = ~blocker;
+ node = TreePtr[ply + 1];
+ ep = board.ep;
+
+ /* Knight & King */
+ for (piece = knight; piece <= king; piece += 4)
+ {
+ b = a[piece];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ BitToMove (sq, MoveArray[piece][sq] & notfriends);
+ }
+ }
+
+ /* Bishops */
+ b = a[bishop];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ d = BishopAttack(sq);
+ BitToMove (sq, d & notfriends);
+ }
+
+ /* Rooks */
+ b = a[rook];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ d = RookAttack(sq);
+ BitToMove (sq, d & notfriends);
+ }
+
+ /* Queen */
+ b = a[queen];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ d = QueenAttack(sq);
+ BitToMove (sq, d & notfriends);
+ }
+
+ /* White pawn moves */
+ e = (board.friends[1^side] | (ep > -1 ? BitPosArray[ep] : NULLBITBOARD));
+ if (side == white)
+ {
+ c = (a[pawn] >> 8) & notblocker; /* 1 square forward */
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t >= 56) /* promotion */
+ {
+ ADDPROMOTE (t-8, t);
+ }
+ else
+ ADDMOVE (t-8, t, 0);
+ }
+
+ b = a[pawn] & RankBit[1]; /* all pawns on 2nd rank */
+ c = (b >> 8) & notblocker;
+ c = (c >> 8) & notblocker; /* 2 squares forward */
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ ADDMOVE (t-16, t, 0);
+ }
+
+ b = a[pawn] & ~FileBit[0]; /* captures to the left */
+ c = (b >> 7) & e;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t >= 56) /* promotion */
+ {
+ ADDPROMOTE (t-7, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t-7, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t-7, t, 0);
+ }
+ }
+
+ b = a[pawn] & ~FileBit[7]; /* captures to the right */
+ c = (b >> 9) & e;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t >= 56) /* promotion */
+ {
+ ADDPROMOTE (t-9, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t-9, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t-9, t, 0);
+ }
+ }
+ }
+
+
+ /* Black pawn forward moves */
+ if (side == black)
+ {
+ c = (a[pawn] << 8) & notblocker;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t <= 7) /* promotion */
+ {
+ ADDPROMOTE (t+8, t);
+ }
+ else
+ ADDMOVE (t+8, t, 0);
+ }
+
+ b = a[pawn] & RankBit[6]; /* all pawns on 7th rank */
+ c = (b << 8) & notblocker;
+ c = (c << 8) & notblocker;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ ADDMOVE (t+16, t, 0);
+ }
+
+ b = a[pawn] & ~FileBit[7]; /* captures to the left */
+ c = (b << 7) & e;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t <= 7) /* promotion */
+ {
+ ADDPROMOTE (t+7, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t+7, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t+7, t, 0);
+ }
+ }
+
+ b = a[pawn] & ~FileBit[0]; /* captures to the right */
+ c = (b << 9) & e;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t <= 7) /* promotion */
+ {
+ ADDPROMOTE (t+9, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t+9, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t+9, t, 0);
+ }
+ }
+ }
+
+ /* Castling code */
+ b = board.b[side][rook];
+ if (side == white && (board.flag & WKINGCASTLE) && (b & BitPosArray[H1]) &&
+ !(FromToRay[E1][G1] & blocker) &&
+ !SqAtakd (E1, black) && !SqAtakd (F1, black) && !SqAtakd (G1, black))
+ {
+ ADDMOVE (E1, G1, CASTLING);
+ }
+ if (side == white && (board.flag & WQUEENCASTLE) && (b & BitPosArray[A1]) &&
+ !(FromToRay[E1][B1] & blocker) &&
+ !SqAtakd (E1, black) && !SqAtakd (D1, black) && !SqAtakd (C1, black))
+ {
+ ADDMOVE (E1, C1, CASTLING);
+ }
+ if (side == black && (board.flag & BKINGCASTLE) && (b & BitPosArray[H8]) &&
+ !(FromToRay[E8][G8] & blocker) &&
+ !SqAtakd (E8, white) && !SqAtakd (F8, white) && !SqAtakd (G8, white))
+ {
+ ADDMOVE (E8, G8, CASTLING);
+ }
+ if (side == black && (board.flag & BQUEENCASTLE) && (b & BitPosArray[A8]) &&
+ !(FromToRay[E8][B8] & blocker) &&
+ !SqAtakd (E8, white) && !SqAtakd (D8, white) && !SqAtakd (C8, white))
+ {
+ ADDMOVE (E8, C8, CASTLING);
+ }
+
+ /* Update tree pointers and count */
+ TreePtr[ply + 1] = node;
+ GenCnt += TreePtr[ply + 1] - TreePtr[ply];
+}
+
+
+void GenNonCaptures (short ply)
+/****************************************************************************
+ *
+ * Here I generate only non-captures. Promotions are considered
+ * as captures and are not generated.
+ *
+ ****************************************************************************/
+{
+ int side;
+ int piece, sq, t, ep;
+ BitBoard b, c, d, friends, notfriends, blocker, notblocker;
+ BitBoard *a;
+
+ side = board.side;
+ a = board.b[side];
+ friends = board.friends[side];
+ notfriends = ~friends;
+ blocker = board.blocker;
+ notblocker = ~blocker;
+ node = TreePtr[ply + 1];
+ ep = board.ep;
+
+ /* Knight & King */
+ for (piece = knight; piece <= king; piece += 4)
+ {
+ b = a[piece];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ BitToMove (sq, MoveArray[piece][sq] & notblocker);
+ }
+ }
+
+ /* Bishops */
+ b = a[bishop];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ d = BishopAttack(sq);
+ BitToMove (sq, d & notblocker);
+ }
+
+ /* Rooks */
+ b = a[rook];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ d = RookAttack(sq);
+ BitToMove (sq, d & notblocker);
+ }
+
+ /* Queen */
+ b = a[queen];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ d = QueenAttack(sq);
+ BitToMove (sq, d & notblocker);
+ }
+
+ /* White pawn moves */
+ if (side == white)
+ {
+ c = (a[pawn] >> 8) & notblocker; /* 1 square forward */
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t < 56)
+ ADDMOVE (t-8, t, 0);
+ }
+
+ b = a[pawn] & RankBit[1]; /* all pawns on 2nd rank */
+ c = (b >> 8) & notblocker;
+ c = (c >> 8) & notblocker; /* 2 squares forward */
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ ADDMOVE (t-16, t, 0);
+ }
+ }
+
+
+ /* Black pawn forward moves */
+ if (side == black)
+ {
+ c = (a[pawn] << 8) & notblocker;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if ( t > 7)
+ ADDMOVE (t+8, t, 0);
+ }
+
+ b = a[pawn] & RankBit[6]; /* all pawns on 7th rank */
+ c = (b << 8) & notblocker;
+ c = (c << 8) & notblocker;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ ADDMOVE (t+16, t, 0);
+ }
+ }
+
+ /* Castling code */
+ b = board.b[side][rook];
+ if (side == white && (board.flag & WKINGCASTLE) && (b & BitPosArray[7]) &&
+ !(FromToRay[4][6] & blocker) &&
+ !SqAtakd (4, black) && !SqAtakd (5, black) && !SqAtakd (6, black))
+ {
+ ADDMOVE (4, 6, CASTLING);
+ }
+ if (side == white && (board.flag & WQUEENCASTLE) && (b & BitPosArray[0]) &&
+ !(FromToRay[4][1] & blocker) &&
+ !SqAtakd (4, black) && !SqAtakd (3, black) && !SqAtakd (2, black))
+ {
+ ADDMOVE (4, 2, CASTLING);
+ }
+ if (side == black && (board.flag & BKINGCASTLE) && (b & BitPosArray[63]) &&
+ !(FromToRay[60][62] & blocker) &&
+ !SqAtakd (60, white) && !SqAtakd (61, white) && !SqAtakd (62, white))
+ {
+ ADDMOVE (60, 62, CASTLING);
+ }
+ if (side == black && (board.flag & BQUEENCASTLE) && (b & BitPosArray[56]) &&
+ !(FromToRay[60][57] & blocker) &&
+ !SqAtakd (60, white) && !SqAtakd (59, white) && !SqAtakd (58, white))
+ {
+ ADDMOVE (60, 58, CASTLING);
+ }
+
+ /* Update tree pointers and count */
+ TreePtr[ply + 1] = node;
+ GenCnt += TreePtr[ply + 1] - TreePtr[ply];
+}
+
+
+void GenCaptures (short ply)
+/****************************************************************************
+ *
+ * This routine generates captures. En passant and pawn promotions
+ * are included.
+ *
+ ****************************************************************************/
+{
+ int side;
+ int piece, sq, t, ep;
+ BitBoard b, c, friends, notfriends, enemy, blocker;
+ BitBoard *a;
+
+ side = board.side;
+ a = board.b[side];
+ friends = board.friends[side];
+ notfriends = ~friends;
+ enemy = board.friends[1^side];
+ blocker = board.blocker;
+ node = TreePtr[ply + 1];
+ ep = board.ep;
+
+ /* Knight & King */
+ for (piece = knight; piece <= king; piece += 4)
+ {
+ b = a[piece];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ BitToMove (sq, MoveArray[piece][sq] & enemy);
+ }
+ }
+
+ /* Bishop */
+ b = a[bishop];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ c = BishopAttack(sq);
+ BitToMove (sq, c & enemy);
+ }
+
+ /* Rook */
+ b = a[rook];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ c = RookAttack(sq);
+ BitToMove (sq, c & enemy);
+ }
+
+ /* Queen */
+ b = a[queen];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ c = QueenAttack(sq);
+ BitToMove (sq, c & enemy);
+ }
+
+ /* White pawn moves */
+ if (side == white)
+ {
+ b = a[pawn] & RankBit[6]; /* all pawns on 7 rank */
+ c = (b >> 8) & ~blocker; /* 1 square forward */
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ ADDPROMOTE (t-8, t);
+ }
+
+ b = a[pawn] & ~FileBit[0]; /* captures to the left */
+ c = (b >> 7) & (board.friends[1^side] | (ep > -1 ? BitPosArray[ep] : ULL(0)));
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t >= 56) /* promotion */
+ {
+ ADDPROMOTE (t-7, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t-7, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t-7, t, 0);
+ }
+ }
+
+ b = a[pawn] & ~FileBit[7]; /* captures to the right */
+ c = (b >> 9) & (board.friends[1^side] | (ep > -1 ? BitPosArray[ep] : ULL(0)));
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t >= 56) /* promotion */
+ {
+ ADDPROMOTE (t-9, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t-9, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t-9, t, 0);
+ }
+ }
+ }
+
+ /* Black pawn forward moves */
+ if (side == black)
+ {
+ b = a[pawn] & RankBit[1]; /* all pawns on 2nd rank */
+ c = (b << 8) & ~blocker;
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ ADDPROMOTE (t+8, t);
+ }
+
+ b = a[pawn] & ~FileBit[7]; /* captures to the left */
+ c = (b << 7) & (board.friends[1^side] | (ep > -1 ? BitPosArray[ep] : ULL(0)));
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t <= 7) /* promotion */
+ {
+ ADDPROMOTE (t+7, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t+7, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t+7, t, 0);
+ }
+ }
+
+ b = a[pawn] & ~FileBit[0]; /* captures to the right */
+ c = (b << 9) & (board.friends[1^side] | (ep > -1 ? BitPosArray[ep] : ULL(0)));
+ while (c)
+ {
+ t = leadz (c);
+ CLEARBIT (c, t);
+ if (t <= 7) /* promotion */
+ {
+ ADDPROMOTE (t+9, t);
+ }
+ else if (ep == t)
+ {
+ ADDMOVE (t+9, t, ENPASSANT);
+ }
+ else
+ {
+ ADDMOVE (t+9, t, 0);
+ }
+ }
+ }
+
+
+ /* Update tree pointers and count */
+ TreePtr[ply + 1] = node;
+ GenCnt += TreePtr[ply + 1] - TreePtr[ply];
+}
+
+
+void GenCheckEscapes (short ply)
+/**************************************************************************
+ *
+ * The king is in check, so generate only moves which get the king out
+ * of check.
+ * Caveat: The special case of an enpassant capture must be taken into
+ * account too as the captured pawn could be the checking piece.
+ *
+ **************************************************************************/
+{
+ int side, xside;
+ int kingsq, chksq, sq, sq1, epsq, dir;
+ BitBoard checkers, b, c, p, escapes;
+ escapes = NULLBITBOARD;
+ side = board.side;
+ xside = 1 ^ side;
+/* TreePtr[ply + 1] = TreePtr[ply]; */
+ node = TreePtr[ply + 1];
+ kingsq = board.king[side];
+ checkers = AttackTo (kingsq, xside);
+ p = board.b[side][pawn];
+
+ if (nbits (checkers) == 1)
+ {
+ /* Captures of checking pieces (except by king) */
+ chksq = leadz (checkers);
+ b = AttackTo (chksq, side);
+ b &= ~board.b[side][king];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ if (!PinnedOnKing (sq, side))
+ {
+ if (cboard[sq] == pawn && (chksq <= H1 || chksq >= A8))
+ {
+ ADDPROMOTE (sq, chksq);
+ }
+ else
+ ADDMOVE (sq, chksq, 0);
+ }
+ }
+
+ /* Maybe enpassant can help */
+ if (board.ep > -1)
+ {
+ epsq = board.ep;
+ if (epsq + (side == white ? -8 : 8) == chksq)
+ {
+ b = MoveArray[ptype[1^side]][epsq] & p;
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ if (!PinnedOnKing (sq, side))
+ ADDMOVE (sq, epsq, ENPASSANT);
+ }
+ }
+ }
+
+ /* Lets block/capture the checking piece */
+ if (slider[cboard[chksq]])
+ {
+ c = FromToRay[kingsq][chksq] & NotBitPosArray[chksq];
+ while (c)
+ {
+ sq = leadz (c);
+ CLEARBIT (c, sq);
+ b = AttackTo (sq, side);
+ b &= ~(board.b[side][king] | p);
+
+ /* Add in pawn advances */
+ if (side == white && sq > H2)
+ {
+ if (BitPosArray[sq-8] & p)
+ b |= BitPosArray[sq-8];
+ if (RANK(sq) == 3 && cboard[sq-8] == empty &&
+ (BitPosArray[sq-16] & p))
+ b |= BitPosArray[sq-16];
+ }
+ if (side == black && sq < H7)
+ {
+ if (BitPosArray[sq+8] & p)
+ b |= BitPosArray[sq+8];
+ if (RANK(sq) == 4 && cboard[sq+8] == empty &&
+ (BitPosArray[sq+16] & p))
+ b |= BitPosArray[sq+16];
+ }
+ while (b)
+ {
+ sq1 = leadz (b);
+ CLEARBIT (b, sq1);
+ if (!PinnedOnKing (sq1, side))
+ {
+ if (cboard[sq1] == pawn && (sq > H7 || sq < A2))
+ {
+ ADDPROMOTE (sq1, sq);
+ }
+ else
+ ADDMOVE (sq1, sq, 0);
+ }
+ }
+ }
+ }
+ }
+
+ /* If more than one checkers, move king to get out of check */
+ if (checkers)
+ escapes = MoveArray[king][kingsq] & ~board.friends[side];
+ while (checkers)
+ {
+ chksq = leadz (checkers);
+ CLEARBIT (checkers, chksq);
+ dir = directions[chksq][kingsq];
+ if (slider[cboard[chksq]])
+ escapes &= ~Ray[chksq][dir];
+ }
+ while (escapes)
+ {
+ sq = leadz (escapes);
+ CLEARBIT (escapes, sq);
+ if (!SqAtakd (sq, xside))
+ ADDMOVE (kingsq, sq, 0);
+ }
+
+ /* Update tree pointers and count */
+ TreePtr[ply + 1] = node;
+ GenCnt += TreePtr[ply + 1] - TreePtr[ply];
+ return;
+}
+
+
+void FilterIllegalMoves (short ply)
+/**************************************************************************
+ *
+ * All the illegal moves in the current ply is removed.
+ *
+ **************************************************************************/
+{
+ leaf *p;
+ int side, xside;
+ int check, sq;
+
+ side = board.side;
+ xside = 1^side;
+ sq = board.king[side];
+ for (p = TreePtr[ply]; p < TreePtr[ply+1]; p++)
+ {
+ MakeMove (side, &p->move);
+ if (cboard[TOSQ(p->move)] != king)
+ check = SqAtakd (sq, xside);
+ else
+ check = SqAtakd (TOSQ(p->move), xside);
+ UnmakeMove (xside, &p->move);
+
+ if (check) /* its an illegal move */
+ {
+ --TreePtr[ply+1];
+ *p = *TreePtr[ply+1];
+ --p;
+ GenCnt--;
+ }
+ }
+}
diff --git a/src/chess_computer-activity/gnuchess/getopt.c b/src/chess_computer-activity/gnuchess/getopt.c
new file mode 100644
index 0000000..ed32692
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/getopt.c
@@ -0,0 +1,1067 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to drepper gnu org
+ before changing it!
+ Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+# ifndef const
+# define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+# define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+# include <stdlib.h>
+# include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+# include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages. */
+# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
+# include <libintl.h>
+# ifndef _
+# define _(msgid) gettext (msgid)
+# endif
+# else
+# define _(msgid) (msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+# include <string.h>
+# define my_index strchr
+#else
+
+# if HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+#ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+#endif
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# ifdef USE_NONOPTION_FLAGS
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+# else
+# define SWAP_FLAGS(ch1, ch2)
+# endif
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int print_errors = opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
+
+ if (argc < 1)
+ return -1;
+
+ optarg = NULL;
+
+ if (optind == 0 || !__getopt_initialized)
+ {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else if (long_only
+ || pfound->has_arg != p->has_arg
+ || pfound->flag != p->flag
+ || pfound->val != p->val)
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (print_errors)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (print_errors)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/src/chess_computer-activity/gnuchess/getopt.h b/src/chess_computer-activity/gnuchess/getopt.h
new file mode 100644
index 0000000..18e1026
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/getopt.h
@@ -0,0 +1,179 @@
+/* Declarations for getopt.
+ Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+ standalone, or this is the first header included in the source file.
+ If we are being used with glibc, we need to include <features.h>, but
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
+ not defined, include <ctype.h>, which will pull in <features.h> for us
+ if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
+ doesn't flood the namespace with stuff the way some other headers do.) */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+# if (defined __STDC__ && __STDC__) || defined __cplusplus
+ const char *name;
+# else
+ char *name;
+# endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `getopt'. */
+
+#if (defined __STDC__ && __STDC__) || defined __cplusplus
+# ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+# else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+# endif /* __GNU_LIBRARY__ */
+
+# ifndef __need_getopt
+extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only);
+# endif
+#else /* not __STDC__ */
+extern int getopt ();
+# ifndef __need_getopt
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+# endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/src/chess_computer-activity/gnuchess/getopt1.c b/src/chess_computer-activity/gnuchess/getopt1.c
new file mode 100644
index 0000000..62c55cf
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/getopt1.c
@@ -0,0 +1,187 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/src/chess_computer-activity/gnuchess/gnome-gnuchess b/src/chess_computer-activity/gnuchess/gnome-gnuchess
new file mode 100755
index 0000000..e0366f6
Binary files /dev/null and b/src/chess_computer-activity/gnuchess/gnome-gnuchess differ
diff --git a/src/chess_computer-activity/gnuchess/hash.c b/src/chess_computer-activity/gnuchess/hash.c
new file mode 100644
index 0000000..5d05145
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/hash.c
@@ -0,0 +1,127 @@
+/* GNU Chess 5.0 - hash.c - hash function code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+
+void CalcHashKey (void)
+/***************************************************************************
+ *
+ * Calculates the hashkey for the current board position. We sometimes
+ * need to do this especially when loading an EPD position.
+ * Note: The hashkey is a 64 bit unsigned integer number.
+ * Added in pawnhashkey calculation.
+ *
+ ***************************************************************************/
+{
+ int sq, piece, color;
+ BitBoard b;
+
+ PawnHashKey = HashKey = (HashType) 0;
+ for (color = white; color <= black; color++)
+ {
+ for (piece = pawn; piece <= king; piece++)
+ {
+ b = board.b[color][piece];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ HashKey ^= hashcode[color][piece][sq];
+ if (piece == pawn)
+ PawnHashKey ^= hashcode[color][piece][sq];
+ }
+ }
+ }
+
+ /* Take into account castling status & en passant */
+ if (board.ep > -1)
+ HashKey ^= ephash[board.ep];
+ if (board.flag & WKINGCASTLE)
+ HashKey ^= WKCastlehash;
+ if (board.flag & WQUEENCASTLE)
+ HashKey ^= WQCastlehash;
+ if (board.flag & BKINGCASTLE)
+ HashKey ^= BKCastlehash;
+ if (board.flag & BQUEENCASTLE)
+ HashKey ^= BQCastlehash;
+
+ /* Take into account side to move */
+ if (board.side == black)
+ HashKey ^= Sidehash;
+
+}
+
+
+void ShowHashKey (HashType HashKey)
+/***************************************************************************
+ *
+ * Just a small utility routine to print out the hashkey (which is 64 bits).
+ *
+ ***************************************************************************/
+{
+ unsigned long a1, a2;
+
+ a1 = HashKey & 0xFFFFFFFF;
+ a2 = (HashKey >> 32);
+ printf ("Hashkey = %lx%lx\n", a2, a1);
+}
+
+void CalcHashSize (int tablesize)
+/***************************************************************************
+ *
+ * Calculates the ttable hashtable size, ttable hashmask, and pawntable hashmask
+ *
+ ***************************************************************************/
+{
+ int i;
+
+ i = (tablesize < HASHSLOTS ? HASHSLOTS : tablesize);
+
+ if ( i > 1073741823 ){
+ printf("Max hashsize exceeded\n");
+ i = 107374183;
+ }
+
+ TTHashMask = 0;
+ while ((i>>=1) > 0)
+ {
+ TTHashMask <<= 1;
+ TTHashMask |= 1;
+ }
+ HashSize = TTHashMask + 1;
+ printf ("Adjusting HashSize to %d slots\n", HashSize);
+
+ i = PAWNSLOTS;
+ PHashMask = 0;
+ while ((i>>=1) > 0)
+ {
+ PHashMask <<= 1;
+ PHashMask |= 1;
+ }
+}
diff --git a/src/chess_computer-activity/gnuchess/hung.c b/src/chess_computer-activity/gnuchess/hung.c
new file mode 100644
index 0000000..b7ce12a
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/hung.c
@@ -0,0 +1,76 @@
+/* GNU Chess 5.0 - hung.c - hung piece evaluation code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ * Hung piece evaluation.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+int EvalHung(int side)
+/****************************************************************************
+ *
+ * Calculate the number of hung pieces for a side.
+ *
+ ****************************************************************************/
+{
+ BitBoard c, n, b, r, q;
+ int xside;
+
+ xside = 1 ^ side;
+ hunged[side] = 0;
+
+ /* Knight */
+ n = (Ataks[xside][pawn] & board.b[side][knight]);
+ n |= (Ataks[xside][0] & board.b[side][knight] & ~Ataks[side][0]);
+
+ /* Bishop */
+ b = (Ataks[xside][pawn] & board.b[side][bishop]);
+ b |= (Ataks[xside][0] & board.b[side][bishop] & ~Ataks[side][0]);
+
+ /* Rook */
+ r = Ataks[xside][pawn] | Ataks[xside][knight] | Ataks[xside][bishop];
+ r = (r & board.b[side][rook]);
+ r |= (Ataks[xside][0] & board.b[side][rook] & ~Ataks[side][0]);
+
+ /* Queen */
+ q = Ataks[xside][pawn] | Ataks[xside][knight] | Ataks[xside][bishop] |
+ Ataks[xside][rook];
+ q = (q & board.b[side][queen]);
+ q |= (Ataks[xside][0] & board.b[side][queen] & ~Ataks[side][0]);
+
+ c = n | b | r | q ;
+
+ if (c)
+ hunged[side] += nbits (c);
+
+ /* King */
+ if (Ataks[xside][0] & board.b[side][king])
+ hunged[side] ++;
+
+ return (hunged[side]);
+}
diff --git a/src/chess_computer-activity/gnuchess/init.c b/src/chess_computer-activity/gnuchess/init.c
new file mode 100644
index 0000000..fa65d58
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/init.c
@@ -0,0 +1,796 @@
+/* GNU Chess 5.0 - init.c - initialization of variables code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "version.h"
+#include "lexpgn.h"
+
+void Initialize (void)
+/**************************************************************************
+ *
+ * The main initialization driver.
+ *
+ **************************************************************************/
+{
+ InitLzArray ();
+ InitBitPosArray ();
+ InitMoveArray ();
+ InitRay ();
+ InitFromToRay ();
+ InitRankFileBit ();
+ InitPassedPawnMask ();
+ InitIsolaniMask ();
+ InitSquarePawnMask ();
+ InitBitCount ();
+ InitRotAtak ();
+ InitRandomMasks ();
+ InitDistance ();
+ InitVars ();
+ InitHashCode ();
+ InitHashTable ();
+ CalcHashKey ();
+ InitInput ();
+}
+
+
+void InitFICS (void)
+{
+ if (flags & XBOARD) {
+ printf ("tellics shout Greetings from %s %s. Ready for a game.\n", PROGRAM, VERSION);
+ printf ("tellics set 1 %s %s.\n",PROGRAM,VERSION);
+ }
+
+}
+
+#define NBITS 16
+
+void InitLzArray (void)
+/***************************************************************************
+ *
+ * The lzArray is created. This array is used when the position
+ * of the leading non-zero bit is required. The convention used
+ * is that the leftmost bit is considered as position 0 and the
+ * rightmost bit position 63.
+ *
+ ***************************************************************************/
+{
+ int i, j, s, n;
+
+ s = n = 1;
+ for (i = 0; i < NBITS; i++)
+ {
+ for (j = s; j < s + n; j++)
+ lzArray[j] = NBITS - 1 - i;
+ s += n;
+ n += n;
+ }
+}
+
+
+void InitBitPosArray (void)
+/***************************************************************************
+ *
+ * BitPosArray[i] returns the bitboard whose ith bit is set to 1
+ * and every other bits 0. This ought to be faster than doing
+ * shifting all the time (I think).
+ * Also compute the NotBitPosArray = ~BitPosArray.
+ *
+ ***************************************************************************/
+{
+ BitBoard b;
+ int i;
+
+ b = (BitBoard) 1;
+ for (i = 63; i >= 0; i--, b <<= 1)
+ {
+ BitPosArray[i] = b;
+ NotBitPosArray[i] = ~b;
+ }
+}
+
+
+
+/* Data used for generating MoveArray */
+
+static const int dir[8][8] =
+{
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 9, 11, 0, 0, 0, 0, 0, 0 },
+ { -21, -19, -12, -8, 8, 12, 19, 21 },
+ { -11, -9, 9, 11, 0, 0, 0, 0 },
+ { -10, -1, 1, 10, 0, 0, 0, 0 },
+ { -11, -10, -9, -1, 1, 9, 10, 11 },
+ { -11, -10, -9, -1, 1, 9, 10, 11 },
+ { -9, -11, 0, 0, 0, 0, 0, 0 }
+};
+static const int ndir[8] =
+{ 0, 2, 8, 4, 4, 8, 8, 2 };
+
+static const int map[120] =
+{
+ -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, -1,
+ -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
+ -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
+ -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
+ -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
+ -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
+ -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+
+void InitMoveArray (void)
+/***************************************************************************
+ *
+ * Generate the move bitboards. For e.g. the bitboard for all
+ * the moves of a knight on f3 is given by MoveArray[knight][21].
+ *
+ ***************************************************************************/
+{
+ int piece, fsq, tsq, f, t, n;
+ BitBoard *b;
+
+ for (piece = pawn; piece <= bpawn; piece++)
+ {
+ for (fsq = 0; fsq < 120; fsq++)
+ {
+ if ((f = map[fsq]) == -1) continue;
+ b = &MoveArray[piece][f];
+ *b = NULLBITBOARD;
+ for (n = 0; n < ndir[piece]; n++)
+ {
+ tsq = fsq;
+ do
+ {
+ tsq += dir[piece][n];
+ if ((t = map[tsq]) != -1)
+ SETBIT (*b, t);
+ } while (range[piece] && t != -1);
+ }
+ }
+ }
+}
+
+
+void InitRay (void)
+/**************************************************************************
+ *
+ * For each square, there are 8 rays. The first 4 rays are diagonals
+ * for the bishops and the next 4 are file/rank for the rooks.
+ * The queen uses all 8 rays.
+ * These rays are used for move generation rather than MoveArray[].
+ * Also initialize the directions[][] array. directions[f][t] returns
+ * the index into Ray[f] array allow us to find the ray in that direction.
+ *
+ **************************************************************************/
+{
+ int piece, fsq, tsq, f, t, n, ray;
+ BitBoard *b;
+
+ memset (directions, -1, sizeof (directions));
+ for (fsq = 0; fsq < 120; fsq++)
+ {
+ if ((f = map[fsq]) == -1) continue;
+ ray = -1;
+ for (piece = bishop; piece <= rook; piece++)
+ {
+ for (n = 0; n < ndir[piece]; n++)
+ {
+ b = &Ray[f][++ray];
+ *b = NULLBITBOARD;
+ tsq = fsq;
+ do
+ {
+ tsq += dir[piece][n];
+ if ((t = map[tsq]) != -1)
+ {
+ SETBIT (*b, t);
+ directions[f][t] = ray;
+ }
+ } while (t != -1);
+ }
+ }
+ }
+}
+
+
+void InitFromToRay (void)
+/***************************************************************************
+ *
+ * The FromToRay[b2][f6] gives the diagonal ray from c3 to f6;
+ * It also produces horizontal/vertical rays as well. If no
+ * ray is possible, then a 0 is returned.
+ *
+ ***************************************************************************/
+{
+ int piece, fsq, tsq, f, t, n;
+ BitBoard *b;
+
+ memset (FromToRay, 0, sizeof (FromToRay));
+ for (piece = bishop; piece <= rook; piece++)
+ {
+ for (fsq = 0; fsq < 120; fsq++)
+ {
+ if ((f = map[fsq]) == -1) continue;
+ for (n = 0; n < ndir[piece]; n++)
+ {
+ tsq = fsq;
+ t = map[tsq];
+ do
+ {
+ b = &FromToRay[f][t];
+ tsq += dir[piece][n];
+ if ((t = map[tsq]) != -1)
+ {
+ SETBIT (FromToRay[f][t], t);
+ FromToRay[f][t] |= *b;
+ }
+ } while (t != -1);
+ }
+ }
+ }
+}
+
+
+void InitRankFileBit (void)
+/***************************************************************************
+ *
+ * RankBit[2] has all the bits on the 3rd rank 1 and others 0.
+ * FileBit[2] has all the bits on the 3rd file 1 and others 0.
+ *
+ ***************************************************************************/
+{
+ BitBoard b;
+ int i;
+
+ i = 8;
+ b = (BitBoard) 255;
+ while (i--)
+ {
+ RankBit[i] = b;
+ b <<= 8;
+ }
+
+ i = 8;
+ b = ULL(0x0101010101010101);
+ while (i--)
+ {
+ FileBit[i] = b;
+ b <<= 1;
+ }
+}
+
+
+void InitRandomMasks (void)
+{
+ mask_kr_trapped_w[0]=BitPosArray[H2];
+ mask_kr_trapped_w[1]=BitPosArray[H1]|BitPosArray[H2];
+ mask_kr_trapped_w[2]=BitPosArray[G1]|BitPosArray[H1]|BitPosArray[H2];
+ mask_qr_trapped_w[0]=BitPosArray[A2];
+ mask_qr_trapped_w[1]=BitPosArray[A1]|BitPosArray[A2];
+ mask_qr_trapped_w[2]=BitPosArray[A1]|BitPosArray[B1]|BitPosArray[A2];
+ mask_kr_trapped_b[0]=BitPosArray[H7];
+ mask_kr_trapped_b[1]=BitPosArray[H8]|BitPosArray[H7];
+ mask_kr_trapped_b[2]=BitPosArray[H8]|BitPosArray[G8]|BitPosArray[H7];
+ mask_qr_trapped_b[0]=BitPosArray[A7];
+ mask_qr_trapped_b[1]=BitPosArray[A8]|BitPosArray[A7];
+ mask_qr_trapped_b[2]=BitPosArray[A8]|BitPosArray[B8]|BitPosArray[A7];
+}
+
+void InitPassedPawnMask (void)
+/**************************************************************************
+ *
+ * The PassedPawnMask variable is used to determine if a pawn is passed.
+ * This mask is basically all 1's from the square in front of the pawn to
+ * the promotion square, also duplicated on both files besides the pawn
+ * file. Other bits will be set to zero.
+ * E.g. PassedPawnMask[white][b3] = 1's in a4-c4-c8-a8 rect, 0 otherwise.
+ *
+ **************************************************************************/
+{
+ unsigned int sq;
+
+ memset (PassedPawnMask, 0, sizeof (PassedPawnMask));
+
+ /* Do for white pawns first */
+ for (sq = 0; sq < 64; sq++)
+ {
+ PassedPawnMask[white][sq] = Ray[sq][7];
+ if (ROW(sq) != 0)
+ PassedPawnMask[white][sq] |= Ray[sq-1][7];
+ if (ROW(sq) != 7)
+ PassedPawnMask[white][sq] |= Ray[sq+1][7];
+ }
+
+ /* Do for black pawns */
+ for (sq = 0; sq < 64; sq++)
+ {
+ PassedPawnMask[black][sq] = Ray[sq][4];
+ if (ROW(sq) != 0)
+ PassedPawnMask[black][sq] |= Ray[sq-1][4];
+ if (ROW(sq) != 7)
+ PassedPawnMask[black][sq] |= Ray[sq+1][4];
+ }
+}
+
+
+void InitIsolaniMask (void)
+/**************************************************************************
+ *
+ * The IsolaniMask variable is used to determine if a pawn is an isolani.
+ * This mask is basically all 1's on files beside the file the pawn is on.
+ * Other bits will be set to zero.
+ * E.g. IsolaniMask[d-file] = 1's in c-file & e-file, 0 otherwise.
+ * IMPORTANT:!!!!
+ * Make sure this routine is called AFTER InitRankFileBit().
+ *
+ **************************************************************************/
+{
+ int i;
+
+ IsolaniMask[0] = FileBit[1];
+ IsolaniMask[7] = FileBit[6];
+ for (i = 1; i <= 6; i++)
+ IsolaniMask[i] = FileBit[i-1] | FileBit[i+1];
+
+}
+
+
+void InitSquarePawnMask (void)
+/**************************************************************************
+ *
+ * The SquarePawnMask is used to determine if a king is in the square of
+ * the passed pawn and is able to prevent it from queening.
+ * Caveat: Pawns on 2nd rank have the same mask as pawns on the 3rd rank
+ * as they can advance 2 squares.
+ *
+ **************************************************************************/
+{
+ unsigned int sq;
+ int len, i, j;
+
+ memset (SquarePawnMask, 0, sizeof (PassedPawnMask));
+ for (sq = 0; sq < 64; sq++)
+ {
+ /* White mask */
+ len = 7 - RANK (sq);
+ i = MAX (sq & 56, sq - len);
+ j = MIN (sq | 7, sq + len);
+ while (i <= j)
+ {
+ SquarePawnMask[white][sq] |= (BitPosArray[i] | FromToRay[i][i|56]);
+ i++;
+ }
+
+ /* Black mask */
+ len = RANK (sq);
+ i = MAX (sq & 56, sq - len);
+ j = MIN (sq | 7, sq + len);
+ while (i <= j)
+ {
+ SquarePawnMask[black][sq] |= (BitPosArray[i] | FromToRay[i][i&7]);
+ i++;
+ }
+ }
+
+ /* For pawns on 2nd rank, they have same mask as pawns on 3rd rank */
+ for (sq = A2; sq <= H2; sq++)
+ SquarePawnMask[white][sq] = SquarePawnMask[white][sq+8];
+ for (sq = A7; sq <= H7; sq++)
+ SquarePawnMask[black][sq] = SquarePawnMask[black][sq-8];
+}
+
+
+void InitBitCount (void)
+/**************************************************************************
+ *
+ * The BitCount array returns the no. of bits present in the 16 bit
+ * input argument. This is use for counting the number of bits set
+ * in a BitBoard (e.g. for mobility count).
+ *
+ **************************************************************************/
+{
+ int i, j, n;
+
+ BitCount[0] = 0;
+ BitCount[1] = 1;
+ i = 1;
+ for (n = 2; n <= 16; n++)
+ {
+ i <<= 1;
+ for (j = i; j <= i + (i-1); j++)
+ BitCount[j] = 1 + BitCount[j - i];
+ }
+}
+
+
+void InitRotAtak (void)
+/**************************************************************************
+ *
+ * The attack tables for a normal chessboard and the rotated chess board
+ * are calculated here.
+ *
+ **************************************************************************/
+{
+ int sq, map, sq1, sq2;
+ int cmap[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
+ int rot1[8] = { A1, A2, A3, A4, A5, A6, A7, A8 };
+ int rot2[8] = { A1, B2, C3, D4, E5, F6, G7, H8 };
+ int rot3[8] = { A8, B7, C6, D5, E4, F3, G2, H1 };
+
+ for (sq = A1; sq <= H1; sq++)
+ {
+ for (map = 0; map < 256; map++)
+ {
+ Rook00Atak[sq][map] = 0;
+ Rook90Atak[rot1[sq]][map] = 0;
+ Bishop45Atak[rot2[sq]][map] = 0;
+ Bishop315Atak[rot3[sq]][map] = 0;
+ sq1 = sq2 = sq;
+ while (sq1 > 0)
+ {
+ if (cmap[--sq1] & map)
+ break;
+ }
+ while (sq2 < 7)
+ {
+ if (cmap[++sq2] & map)
+ break;
+ }
+ Rook00Atak[sq][map] =
+ FromToRay[sq][sq1] | FromToRay[sq][sq2];
+ Rook90Atak[rot1[sq]][map] =
+ FromToRay[rot1[sq]][rot1[sq1]] |
+ FromToRay[rot1[sq]][rot1[sq2]];
+ Bishop45Atak[rot2[sq]][map] =
+ FromToRay[rot2[sq]][rot2[sq1]] |
+ FromToRay[rot2[sq]][rot2[sq2]];
+ Bishop315Atak[rot3[sq]][map] =
+ FromToRay[rot3[sq]][rot3[sq1]] |
+ FromToRay[rot3[sq]][rot3[sq2]];
+ }
+ }
+
+ for (map = 0; map < 256; map++)
+ {
+ for (sq = A2; sq <= H8; sq++)
+ {
+ Rook00Atak[sq][map] = Rook00Atak[sq-8][map] >> 8;
+ }
+
+ for (sq1 = B_FILE; sq1 <= H_FILE; sq1++)
+ {
+ for (sq2 = 0; sq2 < 64; sq2+=8)
+ {
+ sq = sq2 + sq1;
+ Rook90Atak[sq][map] = Rook90Atak[sq-1][map] >> 1;
+ }
+ }
+
+ for (sq1 = B1, sq2 = H7; sq1 <= H1; sq1++, sq2-=8)
+ {
+ for (sq = sq1; sq <= sq2; sq += 9)
+ {
+ Bishop45Atak[sq][map] = Bishop45Atak[sq+8][map] << 8;
+ }
+ }
+ for (sq1 = A2, sq2 = G8; sq1 <= A8; sq1+=8, sq2--)
+ {
+ for (sq = sq1; sq <= sq2; sq += 9)
+ {
+ Bishop45Atak[sq][map] =
+ (Bishop45Atak[sq+1][map] & NotBitPosArray[sq1-8]) << 1;
+ }
+ }
+
+ for (sq1 = H2, sq2 = B8; sq1 <= H8; sq1+=8, sq2++)
+ {
+ for (sq = sq1; sq <= sq2; sq += 7)
+ {
+ Bishop315Atak[sq][map] = Bishop315Atak[sq-8][map] >> 8;
+ }
+ }
+ for (sq1 = G1, sq2 = A7; sq1 >= A1; sq1--, sq2-=8)
+ {
+ for (sq = sq1; sq <= sq2; sq += 7)
+ {
+ Bishop315Atak[sq][map] =
+ (Bishop315Atak[sq+1][map] & NotBitPosArray[sq2+8]) << 1;
+ }
+ }
+ }
+}
+
+
+void InitDistance (void)
+/**************************************************************************
+ *
+ * There are two arrays dealing with distances. The distance[s1][s2]
+ * array gives the minimum number of moves a king takes to get from s1
+ * to s2. The taxicab[s1][s2] array is the taxicab distance. Example:
+ * distance[a1][b3] = 2; taxicab[a1[b3] = 3;
+ *
+ *************************************************************************/
+{
+ int f, t, j;
+ int d1, d2;
+
+ for (f = 0; f < 64; f++)
+ for (t = 0; t < 8; t++)
+ DistMap[f][t] = ULL(0);
+
+
+ for (f = 0; f < 64; f++)
+ for (t = f; t < 64; t++)
+ {
+ d1 = (t & 0x07) - (f & 0x07);
+ if (d1 < 0) d1 = -d1;
+ d2 = (t >> 3) - (f >> 3);
+ if (d2 < 0) d2 = -d2;
+ distance[f][t] = MAX (d1, d2);
+ distance[t][f] = MAX (d1, d2);
+ taxicab[f][t] = d1 + d2;
+ taxicab[t][f] = d1 + d2;
+ }
+
+ for (f = 0; f < 64; f++)
+ for (t = 0; t < 64; t++)
+ DistMap[f][distance[t][f]] |= BitPosArray[t];
+
+ for (f = 0; f < 64; f++)
+ for (t = 0; t < 8; t++)
+ for (j = 0; j < t; j++)
+ DistMap[f][t] |= DistMap[f][j];
+}
+
+
+void InitVars (void)
+/***************************************************************************
+ *
+ * Initialize various variables, especially for new game.
+ *
+ ***************************************************************************/
+{
+ int i;
+
+ /* Initialize board */
+ memset (&board, 0, sizeof (board));
+ for (i = 8; i < 16; i++)
+ SETBIT (board.b[white][pawn], i);
+ SETBIT (board.b[white][rook], 0);
+ SETBIT (board.b[white][knight], 1);
+ SETBIT (board.b[white][bishop], 2);
+ SETBIT (board.b[white][queen], 3);
+ SETBIT (board.b[white][king], 4);
+ SETBIT (board.b[white][bishop], 5);
+ SETBIT (board.b[white][knight], 6);
+ SETBIT (board.b[white][rook], 7);
+ for (i = 48; i < 56; i++)
+ SETBIT (board.b[black][pawn], i);
+ SETBIT (board.b[black][rook], 56);
+ SETBIT (board.b[black][knight], 57);
+ SETBIT (board.b[black][bishop], 58);
+ SETBIT (board.b[black][queen], 59);
+ SETBIT (board.b[black][king], 60);
+ SETBIT (board.b[black][bishop], 61);
+ SETBIT (board.b[black][knight], 62);
+ SETBIT (board.b[black][rook], 63);
+
+ SETBIT (stonewall[white], D4); /* SMC */
+ SETBIT (stonewall[white], E3); /* SMC */
+ SETBIT (stonewall[white], F4); /* SMC */
+
+ SETBIT (stonewall[black], D5); /* SMC */
+ SETBIT (stonewall[black], E6); /* SMC */
+ SETBIT (stonewall[black], F5); /* SMC */
+
+ rings[0] = ULL(0x0000001818000000);
+ rings[1] = ULL(0x00003C24243C0000);
+ rings[2] = ULL(0x007E424242427E00);
+ rings[3] = ULL(0xFF818181818181FF);
+
+ boxes[0] = ULL(0x00003C3C3C3C0000); /* rings[0] | rings[1] */
+ boxes[1] = ULL(0x007E7E7E7E7E7E00); /* rings[0] | rings[1] | rings[2] */
+
+ boardhalf[white] = RankBit[0]|RankBit[1]|RankBit[2]|RankBit[3];
+ boardhalf[black] = RankBit[4]|RankBit[5]|RankBit[6]|RankBit[7];
+ boardside[ks] = FileBit[4]|FileBit[5]|FileBit[6]|FileBit[7];
+ boardside[qs] = FileBit[0]|FileBit[1]|FileBit[2]|FileBit[3];
+
+ board.flag |= (WCASTLE | BCASTLE);
+ RealSide = board.side = white;
+ board.ep = -1;
+ board.king[white] = E1;
+ board.king[black] = E8;
+ RealGameCnt = GameCnt = -1;
+ Game50 = 0;
+ computer = black;
+ CalcHashKey ();
+ Game[0].hashkey = HashKey;
+ board.pmaterial[white] = board.pmaterial[black] =
+ 2*ValueR + 2*ValueN + 2*ValueB + ValueQ;
+ board.material[white] = board.material[black] =
+ board.pmaterial[white] + 8*ValueP;
+
+ /* Initialize pgn values */
+ initial_comments = NULL;
+ /* Reset values; doing this again will cause a trivial memory leak
+ * when reloading PGN files as games, but it's not worth fixing. */
+ pgn_event = pgn_site =
+ pgn_date = pgn_round = pgn_white = pgn_black =
+ pgn_whiteELO = pgn_blackELO = pgn_result =
+ pgn_othertags = NULL;
+
+
+ UpdateFriends ();
+ UpdateCBoard ();
+ UpdateMvboard ();
+
+ for (i = A1; i <= H8; i++)
+ {
+ if (cboard[i])
+ {
+ SETBIT (board.blockerr90, r90[i]);
+ SETBIT (board.blockerr45, r45[i]);
+ SETBIT (board.blockerr315, r315[i]);
+ }
+ }
+
+ /* TreePtr[0] is practically unused. TreePtr[1] points to the
+ * base of the tree.
+ */
+ TreePtr[0] = TreePtr[1] = Tree;
+
+ /* Initialize some of the game flags */
+ SET (flags, USEHASH);
+ SET (flags, USENULL);
+ SearchTime = 5;
+ SearchDepth = 0;
+ board.castled[white] = board.castled[black] = false;
+ phase = PHASE;
+
+/* Calculate the ttable hashmask & pawntable hashmask */
+ if ( HashSize == 0 )
+ CalcHashSize(HashSize);
+
+ signal (SIGINT, EndSearch);
+
+ nmovesfrombook = 0;
+}
+
+
+void InitHashCode (void)
+/***************************************************************************
+ *
+ * The hash code for the various pieces standing on the various squares
+ * are initialized here. When a particular piece is move from square A
+ * to square B, the current hashkey is XORed against the hash code for
+ * the A square and B square to give the new hashkey.
+ *
+ ***************************************************************************/
+{
+ int color, piece, sq;
+
+ for (color = white; color <= black; color++)
+ {
+ for (piece = pawn; piece <= king; piece++)
+ {
+ for (sq = 0; sq < 64; sq++)
+ {
+ hashcode[color][piece][sq] = Rand64 ();
+ }
+ }
+ }
+ for (sq = 0; sq < 64; sq++)
+ ephash[sq] = Rand64 ();
+ WKCastlehash = Rand64 ();
+ WQCastlehash = Rand64 ();
+ BKCastlehash = Rand64 ();
+ BQCastlehash = Rand64 ();
+ Sidehash = Rand64 ();
+}
+
+
+void InitHashTable (void)
+/****************************************************************************
+ *
+ * Allocate memory for our transposition tables. By default, the
+ * transposition table will have 16K entries; 8K for each color.
+ * Add code to allocated memory for pawn table as well.
+ *
+ ****************************************************************************/
+{
+ unsigned int size;
+ unsigned int allocating = 1;
+ /* One can not use realloc() here, it screws up error handling */
+ do {
+ free(HashTab[0]);
+ free(HashTab[1]);
+ HashTab[0] = malloc (HashSize * sizeof (HashSlot));
+ HashTab[1] = malloc (HashSize * sizeof (HashSlot));
+ if (HashTab[0] == NULL || HashTab[1] == NULL) {
+ printf ("Not enough memory for transposition table, trying again.\n");
+ if (HashSize == HASHSLOTS) {
+ fprintf(stderr, "Memory exhausted, goodbye, my friend.\n");
+ exit(EXIT_FAILURE);
+ }
+ CalcHashSize(HashSize>>1);
+ }
+ else
+ allocating = 0;
+ } while (allocating);
+ size = (HashSize * 2 * sizeof (HashSlot)) >> 10;
+ if (!(flags & XBOARD)) {
+ printf ("Transposition table: Entries=%dK Size=%dK\n",
+ HashSize>>10, size);
+ }
+ /*
+ * Here realloc() is O.K., though not very useful, because PAWNSLOTS
+ * is constant anyway.
+ */
+ PawnTab[0] = (PawnSlot *) realloc (PawnTab[0], PAWNSLOTS * sizeof
+(PawnSlot));
+ PawnTab[1] = (PawnSlot *) realloc (PawnTab[1], PAWNSLOTS * sizeof
+(PawnSlot));
+ if (PawnTab[0] == NULL || PawnTab[1] == NULL) {
+ printf ("Not enough memory for pawn table, goodbye.\n");
+ exit(EXIT_FAILURE);
+ } else {
+ size = (PAWNSLOTS * 2 * sizeof (PawnSlot)) >> 10;
+ if (!(flags & XBOARD))
+ printf ("Pawn hash table: Entries=%dK Size=%dK\n",
+ PAWNSLOTS >> 10, size);
+ }
+}
+
+
+void NewPosition (void)
+/****************************************************************************
+ *
+ * Reset some flags for a new game/position.
+ *
+ ****************************************************************************/
+{
+ CLEAR (flags, ENDED);
+ Game50 = 0;
+ RealGameCnt = GameCnt = -1;
+ Game[0].hashkey = HashKey;
+ TTClear ();
+ PTClear ();
+ nmovesfrombook = 0;
+ ExchCnt[white] = ExchCnt[black] = 0;
+}
diff --git a/src/chess_computer-activity/gnuchess/inlines.h b/src/chess_computer-activity/gnuchess/inlines.h
new file mode 100644
index 0000000..ea95b5d
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/inlines.h
@@ -0,0 +1,61 @@
+/* GNU Chess 5.0 - inlines.h - static inline functions
+
+ This file constains static inline version of performance-critical
+ functions. Is included by common.h unless NO_INLINE is defined.
+
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+ lukas debian org
+*/
+
+#ifndef INLINES_H
+#define INLINES_H
+
+static inline unsigned char leadz (BitBoard b)
+/**************************************************************************
+ *
+ * Returns the leading bit in a bitboard. Leftmost bit is 0 and
+ * rightmost bit is 63. Thanks to Robert Hyatt for this algorithm.
+ *
+ ***************************************************************************/
+{
+ if (b >> 48) return lzArray[b >> 48];
+ if (b >> 32) return lzArray[b >> 32] + 16;
+ if (b >> 16) return lzArray[b >> 16] + 32;
+ return lzArray[b] + 48;
+}
+
+
+static inline unsigned char nbits (BitBoard b)
+/***************************************************************************
+ *
+ * Count the number of bits in b.
+ *
+ ***************************************************************************/
+{
+ return BitCount[b>>48] + BitCount[(b>>32) & 0xffff]
+ + BitCount[(b>>16) & 0xffff] + BitCount[b & 0xffff];
+}
+
+#endif /* !INLINES_H */
diff --git a/src/chess_computer-activity/gnuchess/input.c b/src/chess_computer-activity/gnuchess/input.c
new file mode 100644
index 0000000..68c5fd2
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/input.c
@@ -0,0 +1,192 @@
+/* GNU Chess 5.0 - input.c - Input thread and related
+ Copyright (c) 2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+ lukas debian org
+*/
+
+/*
+ * All the pthread stuff should be hidden here, all the
+ * readline things, too. (I.e., all the potentially troublesome
+ * libraries.
+ */
+
+#include <config.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#include "common.h"
+
+#ifdef HAVE_LIBREADLINE
+# ifdef HAVE_READLINE_READLINE_H
+# include <readline/readline.h>
+# include <readline/history.h>
+# else
+extern char* readline(char *);
+extern void add_history(char *);
+# endif
+#endif
+
+/* Variable used to communicate with the main thread */
+volatile int input_status = INPUT_NONE;
+
+char inputstr[MAXSTR];
+
+/*
+ * The readline getline(), notice that even if we have readline,
+ * it is not used if stdin is not a tty.
+ */
+
+#ifdef HAVE_LIBREADLINE
+void getline_readline(char * p)
+{
+ char *inp;
+
+ inp = readline(p);
+ dbg_printf("getline_readline() called, input is >%s<\n", inp ? inp : "NULL");
+ if (inp && *inp) {
+ add_history(inputstr);
+ strncpy(inputstr, inp, MAXSTR-1);
+ inputstr[MAXSTR-1] = '\0';
+ } else {
+ inputstr[0] = '\0';
+ }
+ if (inp) {
+ free(inp);
+ }
+}
+#endif /* HAVE_LIBREADLINE */
+
+/* The generic input routine */
+
+void getline_standard(char *p)
+{
+ if (!(flags & XBOARD)) {
+ fputs(p, stdout);
+ fflush(stdout);
+ }
+ fgets(inputstr, MAXSTR, stdin);
+}
+
+pthread_t input_thread;
+
+/* Mutex and condition variable for thread communication */
+
+static pthread_mutex_t input_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t input_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t wakeup_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER;
+
+/*
+ * Posix threads are used to allow efficent polling for
+ * input when the program is pondering.
+ *
+ * input_status is a boolean to indicate if a command
+ * is being parsed and processed. It is set by
+ * input function, and must be cleared by the thread
+ * that uses the input.
+ *
+ * The main loop may explicitly wait_for_input, or
+ * when pondering will examine the input_status
+ * variable in Iterate.
+ *
+ */
+
+void *input_func(void *arg __attribute__((unused)) )
+{
+ char prompt[MAXSTR] = "";
+
+ while (!(flags & QUIT)) {
+ if (!(flags & XBOARD)) {
+ sprintf(prompt,"%s (%d) : ",
+ RealSide ? "Black" : "White",
+ (RealGameCnt+1)/2 + 1 );
+ }
+ pthread_mutex_lock(&input_mutex);
+ getline_intrl(prompt);
+ input_status = INPUT_AVAILABLE;
+ pthread_cond_signal(&input_cond);
+ pthread_mutex_unlock(&input_mutex);
+
+ pthread_mutex_lock(&wakeup_mutex);
+ /*
+ * Posix waits can wake up spuriously
+ * so we must ensure that we keep waiting
+ * until we are woken by something that has
+ * consumed the input
+ */
+ while ( input_status == INPUT_AVAILABLE ){
+ pthread_cond_wait(&wakeup_cond, &wakeup_mutex);
+ }
+ pthread_mutex_unlock(&wakeup_mutex);
+ }
+ return NULL;
+}
+
+void input_wakeup(void)
+{
+
+ pthread_mutex_lock(&input_mutex);
+ input_status = INPUT_NONE;
+ pthread_mutex_unlock(&input_mutex);
+ pthread_mutex_lock(&wakeup_mutex);
+ pthread_cond_signal(&wakeup_cond);
+ pthread_mutex_unlock(&wakeup_mutex);
+}
+
+void wait_for_input(void)
+{
+ // Read without mutex -- whoops
+ while (input_status == INPUT_NONE) {
+ pthread_mutex_lock(&input_mutex);
+ if (input_status == INPUT_NONE)
+ pthread_cond_wait(&input_cond, &input_mutex);
+ pthread_mutex_unlock(&input_mutex);
+ }
+}
+
+void InitInput(void)
+{
+#ifdef HAVE_LIBREADLINE
+ if (isatty(STDIN_FILENO)) {
+ getline_intrl = getline_readline;
+ using_history();
+ } else {
+ getline_intrl = getline_standard;
+ }
+#else
+ getline_intrl = getline_standard;
+#endif
+ /* Start input thread */
+ pthread_create(&input_thread, NULL, input_func, NULL);
+}
+
+void CleanupInput(void)
+{
+ pthread_join(input_thread, NULL);
+}
diff --git a/src/chess_computer-activity/gnuchess/iterate.c b/src/chess_computer-activity/gnuchess/iterate.c
new file mode 100644
index 0000000..a18bef7
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/iterate.c
@@ -0,0 +1,375 @@
+/* GNU Chess 5.0 - iterate.c - iterative deepening code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include "common.h"
+
+#define WINDOW 75
+
+short InChkDummy, terminal;
+
+void Iterate (void)
+/**************************************************************************
+ *
+ * Begin the iterative deepening code. The variable Idepth represents
+ * the iteration depth.
+ *
+ **************************************************************************/
+{
+ uint8_t side;
+ int score, RootAlpha, RootBeta;
+
+ dbg_printf("Entered iterate().\n");
+ side = board.side;
+
+ /* Note computer is playing side we are making move for. */
+ computerplays = board.side;
+
+ lazyscore[white] = lazyscore[black] = 150; /* was 50 */
+ maxposnscore[white] = maxposnscore[black] = 150;
+ GenCnt = 0;
+ NodeCnt = QuiesCnt = 0;
+ EvalCnt = EvalCall = 0;
+ OneRepCnt = ChkExtCnt = RcpExtCnt = PawnExtCnt = HorzExtCnt = ThrtExtCnt = 0;
+ KingExtCnt = 0;
+ NullCutCnt = FutlCutCnt = 0;
+ TotalGetHashCnt = GoodGetHashCnt = 0;
+ TotalPutHashCnt = CollHashCnt = 0;
+ TotalPawnHashCnt = GoodPawnHashCnt = 0;
+ RootPawns = nbits (board.b[white][pawn] | board.b[black][pawn]);
+ RootPieces = nbits (board.friends[white] | board.friends[black]) -
+ RootPawns;
+ RootMaterial = MATERIAL;
+ RepeatCnt = 0;
+ ElapsedTime = 0.0;
+ StartTime = StartTiming();
+ memset (ChkCnt, 0, sizeof (ChkCnt));
+ memset (ThrtCnt, 0, sizeof (ThrtCnt));
+ memset (history, 0, sizeof (history));
+ memset (killer1, 0, sizeof (killer1));
+ memset (killer2, 0, sizeof (killer2));
+ CLEAR (flags, TIMEOUT);
+ if (flags & TIMECTL)
+ {
+ /* 2 seconds for unknown latencies */
+
+ SearchTime = (TimeLimit[side] - 2) / MoveLimit[side];
+
+ /* Allocate 10% of total time as reserve */
+ /* mcriley - was 9 * S /10 */
+
+ SearchTime = 95 * SearchTime / 100;
+ /* Reserve more if in sudden death */
+ /* mcrikey was 8 * S / 10 */
+
+ if (suddendeath)
+ SearchTime = 92 * SearchTime / 100;
+
+ /* From loss against Ryo Saeba where we ran out of
+ time first move out of book and blundered pawn */
+ /* Book lookups took too long */
+ if ( nmovesfrombook <= 3 ){
+ printf ("Search time bonus near book\n");
+ SearchTime = 1.5 * SearchTime;
+ }
+
+ /* Always target at least the increment seconds for the move! */
+ /* To prevent huge surplus build-up. */
+
+ if (TCinc != 0)
+ if (SearchTime < TCinc) {
+ printf("TimeLimit[%s] = %6.2f\n",side == white ? "White" : "Black" ,TimeLimit[side]);
+ if (TimeLimit[side] > 30) { /* Only if > 15 seconds left */
+ SearchTime = TCinc;
+ }
+ }
+ ShowTime ();
+ }
+ Idepth = 0;
+ TreePtr[2] = TreePtr[1];
+ GenMoves (1);
+ FilterIllegalMoves (1);
+ SortRoot ();
+
+ InChk[1] = SqAtakd (board.king[side], 1^side);
+
+ /* Are there any legal moves? */
+ if (GenCnt == 0)
+ {
+ if (!(flags & ENDED)) { /* Don't give result after mate as it will be muddled */
+ if (InChk[1]) {
+ if (computerplays == black)
+ printf("1-0 {computer loses as black}\n");
+ else if (computerplays == white)
+ printf("0-1 {computer loses as white}\n");
+ } else
+ printf("1/2-1/2 {stalemate}\n");
+ fflush(stdout);
+ }
+ SET (flags, TIMEOUT | ENDED);
+ return;
+ }
+ else if (GenCnt == 1)
+ {
+ RootPV = TreePtr[1]->move;
+ SET (flags, TIMEOUT);
+ }
+ lastrootscore = score = Evaluate (-INFINITY, INFINITY);
+
+ wasbookmove = 0;
+
+ /* Don't look up moves in book in opponents time, think instead */
+
+ if (bookmode != BOOKOFF && !(flags & SOLVE) && !(flags & PONDER) && nmovesfrombook <= 3) {
+ dbg_printf("Doing book lookup.\n");
+ if (BookQuery(0) == BOOK_SUCCESS) {
+ nmovesfrombook = 0;
+ wasbookmove = 1;
+ SET (flags, TIMEOUT);
+ } else
+ nmovesfrombook++;
+ } else
+ nmovesfrombook++;
+
+
+/* mcriley - was 2 * searchtime */
+
+ maxtime = 4 * SearchTime;
+
+ if (flags & POST) {
+ printf ("Root = %d, ", score);
+ printf ("Phase = %d ", phase);
+ }
+ if (ofp != stdout) {
+ fprintf (ofp, "Entered Iterate() for %s.\n",
+ flags & PONDER ? "pondering" : "analyzing");
+ fprintf (ofp,"Root = %d\t", score);
+ fprintf (ofp,"Phase = %d\t", phase);
+ }
+ if (SearchDepth == 0) {
+ if (ofp != stdout)
+ fprintf (ofp,"\nTime = %.2f, Max = %.2f, Left = %.2f, Moves= %d\n",
+ SearchTime,maxtime,TimeLimit[side],MoveLimit[side]);
+ if (flags & POST)
+ printf ("\nTime = %.2f, Max = %.2f, Left = %.2f, Moves = %d\n",
+ SearchTime,maxtime,TimeLimit[side],MoveLimit[side]);
+ } else {
+ if (ofp != stdout)
+ fprintf (ofp,"Depth = %d\n", SearchDepth);
+ if (flags & POST)
+ printf ("Depth = %d\n", SearchDepth);
+ }
+
+ if (flags & POST) {
+ printf("Ply Time Eval Nodes Principal-Variation\n");
+ if (ofp != stdout)
+ fprintf(ofp,"Ply Time Eval Nodes Principal-Variation\n");
+ }
+ while (!(flags & TIMEOUT))
+ {
+ if (score > MATE-255)
+ {
+ RootAlpha = score-1;
+ RootBeta = MATE;
+ }
+ else if (score < -MATE+255)
+ {
+ RootAlpha = -MATE;
+ RootBeta = score+1;
+ }
+ else
+ {
+ RootAlpha = MAX (score - WINDOW, -MATE);
+ RootBeta = MIN (score + WINDOW, MATE);
+ }
+ Idepth += 1; /* increase iteration depth */
+ rootscore = -INFINITY-1;
+ score = SearchRoot (Idepth, RootAlpha, RootBeta);
+ if (score >= RootBeta && score < MATE && !(flags & TIMEOUT))
+ {
+ ShowLine (RootPV, score, '+');
+ rootscore = -INFINITY-1;
+ RootAlpha = RootBeta;
+ RootBeta = INFINITY;
+ score = SearchRoot (Idepth, RootAlpha, RootBeta);
+ }
+ /* If we fail low, then research. */
+ else
+ {
+ if (score <= RootAlpha && !(flags & TIMEOUT))
+ {
+ ShowLine (RootPV, score, '-');
+ rootscore = -INFINITY-1;
+ RootBeta = RootAlpha;
+ RootAlpha = -INFINITY;
+ score = SearchRoot (Idepth, RootAlpha, RootBeta);
+ }
+ }
+
+ /* Print the final PV line */
+ ShowLine (RootPV, score, '.');
+ lastrootscore = score;
+
+
+ /* See if we have time to start another iteration */
+ /* mcriley - was 2 * S / 3 */
+ if (SearchDepth == 0 && (flags & TIMECTL) && ElapsedTime >= 2 * SearchTime / 3)
+ SET (flags, TIMEOUT);
+
+ if (abs(score) + Idepth >= MATE + 1)
+ SET (flags, TIMEOUT);
+
+ if (!(flags & PONDER) && Idepth == SearchDepth)
+ break;
+ }
+
+ /*
+ * Elapsed time is calculated in Search for timed games
+ * work it out here for statistical purposes
+ */
+ ElapsedTime = GetElapsed (StartTime);
+
+ /* For the moment, just bail out if pondering after search */
+ if (flags & PONDER) return;
+/***************************************************************************
+ *
+ * We've finished the search. Do things like update the game history,
+ * time control stuff and print the search result.
+ * mcriley - MoveLimit was = 60
+ ***************************************************************************/
+ SANMove (RootPV, 1);
+ strcpy (Game[GameCnt+1].SANmv, SANmv);
+ Game[GameCnt+1].et = ElapsedTime;
+ MakeMove (side, &RootPV);
+ if (flags & TIMECTL)
+ {
+ if (suddendeath) {
+ if (TimeLimit[side] > 0 && TimeLimit[side] <= 60)
+ MoveLimit[side] = 60;
+ else
+ MoveLimit[side] = 35;
+ printf("MoveLimit is %d\n",MoveLimit[side]);
+ printf("TimeLimit is %f\n",TimeLimit[side]);
+ } else
+ MoveLimit[side]--;
+ TimeLimit[side] -= ElapsedTime;
+ if (TCinc != 0)
+ TimeLimit[side] += TCinc;
+ if (MoveLimit[side] == 0)
+ {
+ MoveLimit[side] = TCMove;
+ }
+ }
+
+ if (flags & XBOARD)
+ {
+ printf ("%d. ... %s\n", GameCnt/2 + 1, AlgbrMove(RootPV));
+ printf ("My move is: %s\n", AlgbrMove(RootPV));
+ fflush(stdout);
+ if (ofp != stdout) {
+ fprintf (ofp,"%d. ... %s\n", GameCnt/2 + 1, AlgbrMove(RootPV));
+ fprintf (ofp,"My move is: %s\n", AlgbrMove(RootPV));
+ fflush(ofp);
+ }
+ }
+ else
+ {
+ if (!wasbookmove) {
+ fprintf (ofp,"\nTime = %.1f Rate=%ld Nodes=[%ld/%ld/%ld] GenCnt=%ld\n",
+ ElapsedTime, ElapsedTime > 0 ?
+ (unsigned long)((NodeCnt + QuiesCnt) / ElapsedTime) : 0,
+ NodeCnt, QuiesCnt, NodeCnt+QuiesCnt, GenCnt);
+ fprintf (ofp,"Eval=[%ld/%ld] RptCnt=%ld NullCut=%ld FutlCut=%ld\n",
+ EvalCnt, EvalCall, RepeatCnt, NullCutCnt, FutlCutCnt);
+ fprintf (ofp,"Ext: Chk=%ld Recap=%ld Pawn=%ld OneRep=%ld Horz=%ld Mate=%ld KThrt=%ld\n",
+ ChkExtCnt, RcpExtCnt, PawnExtCnt, OneRepCnt, HorzExtCnt, ThrtExtCnt,
+ KingExtCnt);
+ fprintf (ofp,"Material=[%d/%d : %d/%d] ",
+ board.pmaterial[white],
+ board.pmaterial[black],
+ board.material[white],
+ board.material[black]);
+ fprintf (ofp,"Lazy=[%d/%d] ", lazyscore[white], lazyscore[black]);
+ fprintf (ofp,"MaxPosnScore=[%d/%d]\n",maxposnscore[white],maxposnscore[black]);
+ fprintf (ofp,"Hash: Success=%ld%% Collision=%ld%% Pawn=%ld%%\n",
+ GoodGetHashCnt*100/(TotalGetHashCnt+1),
+ CollHashCnt*100/(TotalPutHashCnt+1),
+ GoodPawnHashCnt*100/(TotalPawnHashCnt+1));
+ }
+ if (!(flags & SOLVE)) ShowBoard ();
+ printf ("\nMy move is : %s\n", SANmv);
+ fflush(stdout);
+ if (ofp != stdout) {
+ fprintf (ofp,"\nMy move is : %s\n", SANmv);
+ fflush(ofp);
+ }
+ }
+
+/***************************************************************************
+ *
+ * Before we leave, check to see if this is mate or stalemate.
+ *
+ ***************************************************************************/
+ TreePtr[2] = TreePtr[1];
+ GenMoves (1);
+ FilterIllegalMoves (1);
+ if (TreePtr[1] == TreePtr[2])
+ {
+ if (SqAtakd (board.king[board.side], 1^board.side)) {
+ if (computerplays == black)
+ printf("0-1 {computer wins as black}\n");
+ else
+ printf("1-0 {computer wins as white}\n");
+ } else
+ printf("1/2-1/2 {stalemate}\n");
+ fflush(stdout);
+ SET (flags, ENDED);
+ }
+ if (EvaluateDraw () || Repeat() >= 2)
+ {
+ printf("1/2-1/2 {draw}\n");
+ fflush(stdout);
+ SET (flags, ENDED);
+ }
+}
+
+
+double GetElapsed (Timer start)
+{
+ struct timeval t;
+ gettimeofday (&t, NULL);
+ return t.tv_sec - start.tv_sec + (t.tv_usec - start.tv_usec) / 1e6;
+}
+
+Timer StartTiming (void)
+{
+ Timer t;
+ gettimeofday (&t, NULL);
+ return t;
+}
diff --git a/src/chess_computer-activity/gnuchess/lexpgn.c b/src/chess_computer-activity/gnuchess/lexpgn.c
new file mode 100644
index 0000000..bc00d94
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/lexpgn.c
@@ -0,0 +1,3348 @@
+/* A lexical scanner generated by flex*/
+
+/* Scanner skeleton version:
+ * $Header$
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* Some routines like yy_flex_realloc() are emitted as static but are
+ not called by all lexers. This generates warnings in some compilers,
+ notably GCC. Arrange to suppress these. */
+#ifdef __GNUC__
+#define YY_MAY_BE_UNUSED __attribute__((unused))
+#else
+#define YY_MAY_BE_UNUSED
+#endif
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED;
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+static yyconst short yy_nxt[][46] =
+ {
+ {
+ 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+ },
+
+ {
+ 17, 18, 19, 20, 19, 19, 18, 18, 21, 22,
+ 23, 18, 24, 18, 25, 18, 26, 27, 28, 28,
+ 29, 30, 18, 18, 18, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 32, 18
+
+ },
+
+ {
+ 17, 18, 19, 20, 19, 19, 18, 18, 21, 22,
+ 23, 18, 24, 18, 25, 18, 26, 27, 28, 28,
+ 29, 30, 18, 18, 18, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 32, 18
+ },
+
+ {
+ 17, 33, 33, 34, 33, 34, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33
+
+ },
+
+ {
+ 17, 33, 33, 34, 33, 34, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33
+ },
+
+ {
+ 17, 35, 36, 37, 35, 38, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 39, 39, 39, 39,
+ 35, 35, 35, 40, 39, 39, 41, 39, 42, 43,
+ 44, 39, 39, 39, 39, 39, 39, 39, 45, 46,
+ 39, 39, 39, 47, 35, 35
+
+ },
+
+ {
+ 17, 35, 36, 37, 35, 38, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 39, 39, 39, 39,
+ 35, 35, 35, 40, 39, 39, 41, 39, 42, 43,
+ 44, 39, 39, 39, 39, 39, 39, 39, 45, 46,
+ 39, 39, 39, 47, 35, 35
+ },
+
+ {
+ 17, 48, 49, 34, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48
+
+ },
+
+ {
+ 17, 48, 49, 34, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48
+ },
+
+ {
+ 17, 50, 50, 51, 50, 52, 50, 53, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 54, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50
+
+ },
+
+ {
+ 17, 50, 50, 51, 50, 52, 50, 53, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 54, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50
+ },
+
+ {
+ 17, 55, 55, 34, 55, 34, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55
+
+ },
+
+ {
+ 17, 55, 55, 34, 55, 34, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55
+ },
+
+ {
+ 17, 56, 56, 57, 56, 58, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 59
+
+ },
+
+ {
+ 17, 56, 56, 57, 56, 58, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 59
+ },
+
+ {
+ 17, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 61, 62, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 63, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60
+
+ },
+
+ {
+ 17, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 61, 62, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 64, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60
+ },
+
+ {
+ -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
+ -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
+ -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
+ -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
+ -17, -17, -17, -17, -17, -17
+
+ },
+
+ {
+ 17, -18, -18, -18, -18, -18, -18, -18, -18, -18,
+ -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
+ -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
+ -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
+ -18, -18, -18, -18, -18, -18
+ },
+
+ {
+ 17, -19, 65, 65, 65, 65, -19, -19, -19, -19,
+ -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
+ -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
+ -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
+ -19, -19, -19, -19, -19, -19
+
+ },
+
+ {
+ 17, -20, 65, 65, 65, 65, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20
+ },
+
+ {
+ 17, 66, -21, -21, -21, -21, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66
+
+ },
+
+ {
+ 17, 67, 67, -22, 67, -22, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67
+ },
+
+ {
+ 17, -23, -23, -23, -23, -23, -23, -23, -23, -23,
+ -23, -23, -23, -23, -23, -23, -23, -23, -23, -23,
+ -23, -23, -23, -23, -23, -23, -23, -23, -23, -23,
+ -23, -23, -23, -23, -23, -23, -23, -23, -23, -23,
+ -23, -23, -23, -23, -23, -23
+
+ },
+
+ {
+ 17, -24, 68, 68, 68, 68, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24
+ },
+
+ {
+ 17, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -25, -25, -25, -25, 69, -25, -25, -25, -25, -25,
+ -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
+ -25, -25, -25, -25, -25, -25
+
+ },
+
+ {
+ 17, -26, -26, -26, -26, -26, 70, -26, -26, -26,
+ -26, -26, -26, 71, -26, -26, 70, 70, 70, 70,
+ -26, -26, -26, -26, -26, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, -26, -26
+ },
+
+ {
+ 17, -27, -27, -27, -27, -27, -27, -27, -27, -27,
+ -27, -27, -27, 72, 73, 74, 75, 75, 75, 75,
+ -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
+ -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
+ -27, -27, -27, -27, -27, -27
+
+ },
+
+ {
+ 17, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+ -28, -28, -28, -28, 73, -28, 75, 75, 75, 75,
+ -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+ -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
+ -28, -28, -28, -28, -28, -28
+ },
+
+ {
+ 17, 76, 76, -29, 76, -29, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76
+
+ },
+
+ {
+ 17, -30, 77, -30, -30, -30, -30, -30, -30, -30,
+ -30, -30, -30, -30, -30, -30, -30, -30, -30, -30,
+ -30, -30, -30, -30, -30, -30, -30, -30, -30, -30,
+ -30, -30, -30, -30, -30, -30, -30, -30, -30, -30,
+ -30, -30, -30, -30, -30, -30
+ },
+
+ {
+ 17, -31, -31, -31, -31, -31, 70, -31, -31, -31,
+ -31, -31, -31, 70, -31, -31, 70, 70, 70, 70,
+ -31, -31, -31, -31, -31, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, -31, -31
+
+ },
+
+ {
+ 17, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32
+ },
+
+ {
+ 17, 78, 78, -33, 78, -33, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78
+
+ },
+
+ {
+ 17, -34, -34, -34, -34, -34, -34, -34, -34, -34,
+ -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
+ -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
+ -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
+ -34, -34, -34, -34, -34, -34
+ },
+
+ {
+ 17, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
+ -35, -35, -35, -35, -35, -35
+
+ },
+
+ {
+ 17, -36, 79, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, 80, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36
+ },
+
+ {
+ 17, -37, -37, -37, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37
+
+ },
+
+ {
+ 17, -38, -38, -38, -38, -38, -38, -38, -38, -38,
+ -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
+ -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
+ -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
+ -38, -38, -38, -38, -38, -38
+ },
+
+ {
+ 17, -39, -39, -39, -39, -39, -39, -39, -39, -39,
+ -39, -39, -39, -39, -39, -39, 81, 81, 81, 81,
+ -39, -39, -39, -39, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -39, -39
+
+ },
+
+ {
+ 17, -40, -40, -40, -40, -40, -40, -40, -40, -40,
+ -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
+ -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
+ -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
+ -40, -40, -40, -40, -40, -40
+ },
+
+ {
+ 17, -41, -41, -41, -41, -41, -41, -41, -41, -41,
+ -41, -41, -41, -41, -41, -41, 81, 81, 81, 81,
+ -41, -41, -41, -41, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 82, 81, 81, 81, 81,
+ 81, 81, 81, 81, -41, -41
+
+ },
+
+ {
+ 17, -42, -42, -42, -42, -42, -42, -42, -42, -42,
+ -42, -42, -42, -42, -42, -42, 81, 81, 81, 81,
+ -42, -42, -42, -42, 81, 83, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -42, -42
+ },
+
+ {
+ 17, -43, -43, -43, -43, -43, -43, -43, -43, -43,
+ -43, -43, -43, -43, -43, -43, 81, 81, 81, 81,
+ -43, -43, -43, -43, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 84, 81, -43, -43
+
+ },
+
+ {
+ 17, -44, -44, -44, -44, -44, -44, -44, -44, -44,
+ -44, -44, -44, -44, -44, -44, 81, 81, 81, 81,
+ -44, -44, -44, -44, 81, 81, 81, 81, 81, 85,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -44, -44
+ },
+
+ {
+ 17, -45, -45, -45, -45, -45, -45, -45, -45, -45,
+ -45, -45, -45, -45, -45, -45, 81, 81, 81, 81,
+ -45, -45, -45, -45, 81, 81, 81, 81, 81, 86,
+ 81, 81, 81, 81, 81, 81, 81, 87, 81, 81,
+ 81, 81, 81, 81, -45, -45
+
+ },
+
+ {
+ 17, -46, -46, -46, -46, -46, -46, -46, -46, -46,
+ -46, -46, -46, -46, -46, -46, 81, 81, 81, 81,
+ -46, -46, -46, -46, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 88, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -46, -46
+ },
+
+ {
+ 17, -47, -47, -47, -47, -47, -47, -47, -47, -47,
+ -47, -47, -47, -47, -47, -47, 81, 81, 81, 81,
+ -47, -47, -47, -47, 81, 81, 81, 81, 81, 81,
+ 81, 81, 89, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -47, -47
+
+ },
+
+ {
+ 17, -48, -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
+ -48, -48, -48, -48, -48, -48
+ },
+
+ {
+ 17, -49, 90, -49, -49, -49, -49, 91, -49, -49,
+ -49, -49, -49, -49, -49, -49, -49, -49, -49, -49,
+ -49, -49, -49, -49, -49, -49, -49, -49, -49, -49,
+ -49, -49, -49, -49, -49, -49, -49, -49, -49, -49,
+ -49, -49, -49, -49, -49, -49
+
+ },
+
+ {
+ 17, 92, 92, -50, 92, -50, 92, -50, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 93, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92
+ },
+
+ {
+ 17, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51
+
+ },
+
+ {
+ 17, -52, -52, -52, -52, -52, -52, -52, -52, -52,
+ -52, -52, -52, -52, -52, -52, -52, -52, -52, -52,
+ -52, -52, -52, -52, -52, -52, -52, -52, -52, -52,
+ -52, -52, -52, -52, -52, -52, -52, -52, -52, -52,
+ -52, -52, -52, -52, -52, -52
+ },
+
+ {
+ 17, 94, 95, -53, 94, -53, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 96, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94
+
+ },
+
+ {
+ 17, 92, 92, -54, 92, -54, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 93, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92
+ },
+
+ {
+ 17, 97, 97, -55, 97, -55, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97
+
+ },
+
+ {
+ 17, 98, 98, 99, 98, -56, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, -56
+ },
+
+ {
+ 17, -57, -57, -57, -57, 100, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57
+
+ },
+
+ {
+ 17, -58, -58, 101, -58, -58, -58, -58, -58, -58,
+ -58, -58, -58, -58, -58, -58, -58, -58, -58, -58,
+ -58, -58, -58, -58, -58, -58, -58, -58, -58, -58,
+ -58, -58, -58, -58, -58, -58, -58, -58, -58, -58,
+ -58, -58, -58, -58, -58, -58
+ },
+
+ {
+ 17, -59, -59, -59, -59, -59, -59, -59, -59, -59,
+ -59, -59, -59, -59, -59, -59, -59, -59, -59, -59,
+ -59, -59, -59, -59, -59, -59, -59, -59, -59, -59,
+ -59, -59, -59, -59, -59, -59, -59, -59, -59, -59,
+ -59, -59, -59, -59, -59, -59
+
+ },
+
+ {
+ 17, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ -60, -60, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, -60, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102
+ },
+
+ {
+ 17, -61, -61, -61, -61, -61, -61, -61, -61, -61,
+ -61, -61, -61, -61, -61, -61, -61, -61, -61, -61,
+ -61, -61, -61, -61, -61, -61, -61, -61, -61, -61,
+ -61, -61, -61, -61, -61, -61, -61, -61, -61, -61,
+ -61, -61, -61, -61, -61, -61
+
+ },
+
+ {
+ 17, -62, -62, -62, -62, -62, -62, -62, -62, -62,
+ -62, -62, -62, -62, -62, -62, -62, -62, -62, -62,
+ -62, -62, -62, -62, -62, -62, -62, -62, -62, -62,
+ -62, -62, -62, -62, -62, -62, -62, -62, -62, -62,
+ -62, -62, -62, -62, -62, -62
+ },
+
+ {
+ 17, -63, -63, -63, -63, -63, -63, -63, -63, -63,
+ -63, -63, -63, -63, -63, -63, -63, -63, -63, -63,
+ -63, -63, -63, -63, -63, -63, -63, -63, -63, -63,
+ -63, -63, -63, -63, -63, -63, -63, -63, -63, -63,
+ -63, -63, -63, -63, -63, -63
+
+ },
+
+ {
+ 17, -64, -64, -64, -64, -64, -64, -64, -64, -64,
+ -64, -64, -64, -64, -64, -64, -64, -64, -64, -64,
+ -64, -64, -64, -64, -64, -64, -64, -64, -64, -64,
+ -64, -64, -64, -64, -64, -64, -64, -64, -64, -64,
+ -64, -64, -64, 103, -64, -64
+ },
+
+ {
+ 17, -65, 65, 65, 65, 65, -65, -65, -65, -65,
+ -65, -65, -65, -65, -65, -65, -65, -65, -65, -65,
+ -65, -65, -65, -65, -65, -65, -65, -65, -65, -65,
+ -65, -65, -65, -65, -65, -65, -65, -65, -65, -65,
+ -65, -65, -65, -65, -65, -65
+
+ },
+
+ {
+ 17, 66, -66, -66, -66, -66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66
+ },
+
+ {
+ 17, 67, 67, -67, 67, -67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67
+
+ },
+
+ {
+ 17, -68, 68, 68, 68, 68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68
+ },
+
+ {
+ 17, -69, -69, -69, -69, -69, -69, -69, -69, -69,
+ -69, -69, -69, -69, 69, -69, -69, -69, -69, -69,
+ -69, -69, -69, -69, -69, -69, -69, -69, -69, -69,
+ -69, -69, -69, -69, -69, -69, -69, -69, -69, -69,
+ -69, -69, -69, -69, -69, -69
+
+ },
+
+ {
+ 17, -70, -70, -70, -70, -70, 70, -70, -70, -70,
+ -70, -70, -70, 70, -70, -70, 70, 70, 70, 70,
+ -70, -70, -70, -70, -70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, -70, -70
+ },
+
+ {
+ 17, -71, -71, -71, -71, -71, 70, -71, -71, -71,
+ -71, -71, -71, 70, -71, -71, 70, 104, 70, 70,
+ -71, -71, -71, -71, -71, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, -71, -71
+
+ },
+
+ {
+ 17, -72, -72, -72, -72, -72, -72, -72, -72, -72,
+ -72, -72, -72, -72, -72, -72, 105, -72, -72, -72,
+ -72, -72, -72, -72, -72, -72, -72, -72, -72, -72,
+ -72, -72, -72, -72, -72, -72, -72, -72, -72, -72,
+ -72, -72, -72, -72, -72, -72
+ },
+
+ {
+ 17, -73, -73, -73, -73, -73, -73, -73, -73, -73,
+ -73, -73, -73, -73, -73, -73, -73, -73, -73, -73,
+ -73, -73, -73, -73, -73, -73, -73, -73, -73, -73,
+ -73, -73, -73, -73, -73, -73, -73, -73, -73, -73,
+ -73, -73, -73, -73, -73, -73
+
+ },
+
+ {
+ 17, -74, -74, -74, -74, -74, -74, -74, -74, -74,
+ -74, -74, -74, -74, -74, -74, -74, -74, 106, -74,
+ -74, -74, -74, -74, -74, -74, -74, -74, -74, -74,
+ -74, -74, -74, -74, -74, -74, -74, -74, -74, -74,
+ -74, -74, -74, -74, -74, -74
+ },
+
+ {
+ 17, -75, -75, -75, -75, -75, -75, -75, -75, -75,
+ -75, -75, -75, -75, 73, -75, 75, 75, 75, 75,
+ -75, -75, -75, -75, -75, -75, -75, -75, -75, -75,
+ -75, -75, -75, -75, -75, -75, -75, -75, -75, -75,
+ -75, -75, -75, -75, -75, -75
+
+ },
+
+ {
+ 17, 76, 76, -76, 76, -76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76
+ },
+
+ {
+ 17, -77, 77, -77, -77, -77, -77, -77, -77, -77,
+ -77, -77, -77, -77, -77, -77, -77, -77, -77, -77,
+ -77, -77, -77, -77, -77, -77, -77, -77, -77, -77,
+ -77, -77, -77, -77, -77, -77, -77, -77, -77, -77,
+ -77, -77, -77, -77, -77, -77
+
+ },
+
+ {
+ 17, 78, 78, -78, 78, -78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78
+ },
+
+ {
+ 17, -79, 79, -79, -79, -79, -79, -79, -79, -79,
+ -79, -79, -79, -79, -79, -79, -79, -79, -79, -79,
+ -79, -79, -79, 80, -79, -79, -79, -79, -79, -79,
+ -79, -79, -79, -79, -79, -79, -79, -79, -79, -79,
+ -79, -79, -79, -79, -79, -79
+
+ },
+
+ {
+ 17, -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, -80, -80, -80, -80, -80, -80, -80, -80, -80,
+ -80, -80, -80, -80, -80, -80
+ },
+
+ {
+ 17, -81, -81, -81, -81, -81, -81, -81, -81, -81,
+ -81, -81, -81, -81, -81, -81, 81, 81, 81, 81,
+ -81, -81, -81, -81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -81, -81
+
+ },
+
+ {
+ 17, -82, -82, -82, -82, -82, -82, -82, -82, -82,
+ -82, -82, -82, -82, -82, -82, 81, 81, 81, 81,
+ -82, -82, -82, -82, 81, 107, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -82, -82
+ },
+
+ {
+ 17, -83, -83, -83, -83, -83, -83, -83, -83, -83,
+ -83, -83, -83, -83, -83, -83, 81, 81, 81, 81,
+ -83, -83, -83, -83, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 108, 81, 81, 81, -83, -83
+
+ },
+
+ {
+ 17, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 81, 81, 81, 81,
+ -84, -84, -84, -84, 81, 81, 81, 81, 81, 109,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -84, -84
+ },
+
+ {
+ 17, -85, -85, -85, -85, -85, -85, -85, -85, -85,
+ -85, -85, -85, -85, -85, -85, 81, 81, 81, 81,
+ -85, -85, -85, -85, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 110, 81, 81, 81,
+ 81, 81, 81, 81, -85, -85
+
+ },
+
+ {
+ 17, -86, -86, -86, -86, -86, -86, -86, -86, -86,
+ -86, -86, -86, -86, -86, -86, 81, 81, 81, 81,
+ -86, -86, -86, -86, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 111,
+ 81, 81, 81, 81, -86, -86
+ },
+
+ {
+ 17, -87, -87, -87, -87, -87, -87, -87, -87, -87,
+ -87, -87, -87, -87, -87, -87, 81, 81, 81, 81,
+ -87, -87, -87, -87, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 112, 81, 81, -87, -87
+
+ },
+
+ {
+ 17, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, 81, 81, 81, 81,
+ -88, -88, -88, -88, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 113, 81, 81, 81, -88, -88
+ },
+
+ {
+ 17, -89, -89, -89, -89, -89, -89, -89, -89, -89,
+ -89, -89, -89, -89, -89, -89, 81, 81, 81, 81,
+ -89, -89, -89, -89, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 114, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -89, -89
+
+ },
+
+ {
+ 17, -90, 90, -90, -90, -90, -90, 91, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, -90, -90, -90, -90, -90, -90,
+ -90, -90, -90, -90, -90, -90
+ },
+
+ {
+ 17, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91
+
+ },
+
+ {
+ 17, 92, 92, -92, 92, -92, 92, -92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 93, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92
+ },
+
+ {
+ 17, 92, 92, -93, 92, -93, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 93, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92
+
+ },
+
+ {
+ 17, 94, 94, -94, 94, -94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94
+ },
+
+ {
+ 17, 94, 95, -95, 94, -95, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 96, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94
+
+ },
+
+ {
+ 17, 94, 94, 115, 94, 115, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94
+ },
+
+ {
+ 17, 97, 97, -97, 97, -97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97
+
+ },
+
+ {
+ 17, 98, 98, 99, 98, -98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, -98
+ },
+
+ {
+ 17, 116, 116, 99, 116, -99, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, -99
+
+ },
+
+ {
+ 17, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, -100, -100, -100
+ },
+
+ {
+ 17, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+ -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+ -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+ -101, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+ -101, -101, -101, -101, -101, -101
+
+ },
+
+ {
+ 17, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ -102, -102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, -102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102
+ },
+
+ {
+ 17, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, 117, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103
+
+ },
+
+ {
+ 17, -104, 118, 118, 118, 118, 70, -104, -104, -104,
+ -104, -104, -104, 70, -104, -104, 70, 70, 70, 70,
+ -104, -104, -104, -104, -104, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, -104, -104
+ },
+
+ {
+ 17, -105, 119, 119, 119, 119, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105
+
+ },
+
+ {
+ 17, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, 120, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+ -106, -106, -106, -106, -106, -106
+ },
+
+ {
+ 17, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+ -107, -107, -107, -107, -107, -107, 81, 81, 81, 81,
+ -107, -107, -107, -107, 81, 81, 81, 121, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -107, -107
+
+ },
+
+ {
+ 17, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+ -108, -108, -108, -108, -108, -108, 81, 81, 81, 81,
+ -108, -108, -108, -108, 81, 81, 81, 81, 81, 122,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -108, -108
+ },
+
+ {
+ 17, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+ -109, -109, -109, -109, -109, -109, 81, 81, 81, 81,
+ -109, -109, -109, -109, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 123, 81, 81, 81,
+ 81, 81, 81, 81, -109, -109
+
+ },
+
+ {
+ 17, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+ -110, -110, -110, -110, -110, -110, 81, 81, 81, 81,
+ -110, -110, -110, -110, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -110, -110
+ },
+
+ {
+ 17, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+ -111, -111, -111, -111, -111, -111, 81, 81, 81, 81,
+ -111, -111, -111, -111, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 124, 81, 81, -111, -111
+
+ },
+
+ {
+ 17, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+ -112, -112, -112, -112, -112, -112, 81, 81, 81, 81,
+ -112, -112, -112, -112, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 125, 81, 81, 81,
+ 81, 81, 81, 81, -112, -112
+ },
+
+ {
+ 17, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+ -113, -113, -113, -113, -113, -113, 81, 81, 81, 81,
+ -113, -113, -113, -113, 81, 81, 81, 81, 81, 126,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -113, -113
+
+ },
+
+ {
+ 17, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+ -114, -114, -114, -114, -114, -114, 81, 81, 81, 81,
+ -114, -114, -114, -114, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 127, 81, 81, 81, -114, -114
+ },
+
+ {
+ 17, -115, -115, 115, -115, 115, -115, -115, -115, -115,
+ -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+ -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+ -115, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+ -115, -115, -115, -115, -115, -115
+
+ },
+
+ {
+ 17, 116, 116, 99, 116, -116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, -116
+ },
+
+ {
+ 17, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+ -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+ -117, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+ -117, -117, -117, 128, -117, -117, -117, -117, -117, -117,
+ -117, -117, -117, -117, -117, -117
+
+ },
+
+ {
+ 17, -118, 118, 118, 118, 118, -118, -118, -118, -118,
+ -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+ -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+ -118, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+ -118, -118, -118, -118, -118, -118
+ },
+
+ {
+ 17, -119, 119, 119, 119, 119, -119, -119, -119, -119,
+ -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+ -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+ -119, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+ -119, -119, -119, -119, -119, -119
+
+ },
+
+ {
+ 17, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+ -120, -120, -120, -120, -120, -120, -120, 129, -120, -120,
+ -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+ -120, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+ -120, -120, -120, -120, -120, -120
+ },
+
+ {
+ 17, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+ -121, -121, -121, -121, -121, -121, 81, 81, 81, 81,
+ -121, -121, -121, -121, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 130, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -121, -121
+
+ },
+
+ {
+ 17, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+ -122, -122, -122, -122, -122, -122, 81, 81, 81, 81,
+ -122, -122, -122, -122, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -122, -122
+ },
+
+ {
+ 17, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+ -123, -123, -123, -123, -123, -123, 81, 81, 81, 81,
+ -123, -123, -123, -123, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 131, 81, 81, 81, -123, -123
+
+ },
+
+ {
+ 17, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+ -124, -124, -124, -124, -124, -124, 81, 81, 81, 81,
+ -124, -124, -124, -124, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 132, 81, 81, 81, 81,
+ 81, 81, 81, 81, -124, -124
+ },
+
+ {
+ 17, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+ -125, -125, -125, -125, -125, -125, 81, 81, 81, 81,
+ -125, -125, -125, -125, 81, 81, 81, 81, 133, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -125, -125
+
+ },
+
+ {
+ 17, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+ -126, -126, -126, -126, -126, -126, 81, 81, 81, 81,
+ -126, -126, -126, -126, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -126, -126
+ },
+
+ {
+ 17, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+ -127, -127, -127, -127, -127, -127, 81, 81, 81, 81,
+ -127, -127, -127, -127, 81, 81, 81, 81, 81, 134,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -127, -127
+
+ },
+
+ {
+ 17, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+ -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+ -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+ -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+ 135, -128, -128, -128, -128, -128
+ },
+
+ {
+ 17, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+ -129, -129, -129, -129, -129, 136, -129, -129, -129, -129,
+ -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+ -129, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+ -129, -129, -129, -129, -129, -129
+
+ },
+
+ {
+ 17, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+ -130, -130, -130, -130, -130, -130, 81, 81, 81, 81,
+ -130, -130, -130, -130, 81, 81, 81, 81, 81, 137,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 138, 81, 81, 81, -130, -130
+ },
+
+ {
+ 17, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+ -131, -131, -131, -131, -131, -131, 81, 81, 81, 81,
+ -131, -131, -131, -131, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -131, -131
+
+ },
+
+ {
+ 17, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+ -132, -132, -132, -132, -132, -132, 81, 81, 81, 81,
+ -132, -132, -132, -132, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 139, 81, 81, 81, -132, -132
+ },
+
+ {
+ 17, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+ -133, -133, -133, -133, -133, -133, 81, 81, 81, 81,
+ -133, -133, -133, -133, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -133, -133
+
+ },
+
+ {
+ 17, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+ -134, -134, -134, -134, -134, -134, 81, 81, 81, 81,
+ -134, -134, -134, -134, 81, 81, 81, 81, 81, 140,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 141, 81, 81, 81, -134, -134
+ },
+
+ {
+ 17, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+ -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+ -135, -135, -135, -135, -135, -135, -135, -135, -135, 142,
+ -135, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+ -135, -135, -135, -135, -135, -135
+
+ },
+
+ {
+ 17, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+ -136, -136, -136, -136, -136, -136, -136, -136, 143, -136,
+ -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+ -136, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+ -136, -136, -136, -136, -136, -136
+ },
+
+ {
+ 17, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+ -137, -137, -137, -137, -137, -137, 81, 81, 81, 81,
+ -137, -137, -137, -137, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 144, 81, 81, 81, 81,
+ 81, 81, 81, 81, -137, -137
+
+ },
+
+ {
+ 17, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+ -138, -138, -138, -138, -138, -138, 81, 81, 81, 81,
+ -138, -138, -138, -138, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 145, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -138, -138
+ },
+
+ {
+ 17, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+ -139, -139, -139, -139, -139, -139, 81, 81, 81, 81,
+ -139, -139, -139, -139, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -139, -139
+
+ },
+
+ {
+ 17, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+ -140, -140, -140, -140, -140, -140, 81, 81, 81, 81,
+ -140, -140, -140, -140, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 146, 81, 81, 81, 81,
+ 81, 81, 81, 81, -140, -140
+ },
+
+ {
+ 17, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+ -141, -141, -141, -141, -141, -141, 81, 81, 81, 81,
+ -141, -141, -141, -141, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 147, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -141, -141
+
+ },
+
+ {
+ 17, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+ -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+ -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+ -142, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+ -142, -142, -142, -142, -142, -142
+ },
+
+ {
+ 17, -143, 148, 148, 148, 148, -143, -143, -143, -143,
+ -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+ -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+ -143, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+ -143, -143, -143, -143, -143, -143
+
+ },
+
+ {
+ 17, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+ -144, -144, -144, -144, -144, -144, 81, 81, 81, 81,
+ -144, -144, -144, -144, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 149, 81, 81,
+ 81, 81, 81, 81, -144, -144
+ },
+
+ {
+ 17, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+ -145, -145, -145, -145, -145, -145, 81, 81, 81, 81,
+ -145, -145, -145, -145, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 150, 81, 81, 81, -145, -145
+
+ },
+
+ {
+ 17, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+ -146, -146, -146, -146, -146, -146, 81, 81, 81, 81,
+ -146, -146, -146, -146, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 151, 81, 81,
+ 81, 81, 81, 81, -146, -146
+ },
+
+ {
+ 17, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, 81, 81, 81, 81,
+ -147, -147, -147, -147, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 152, 81, 81, 81, -147, -147
+
+ },
+
+ {
+ 17, -148, 148, 148, 148, 148, -148, -148, -148, -148,
+ -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+ -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+ -148, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+ -148, -148, -148, -148, -148, -148
+ },
+
+ {
+ 17, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+ -149, -149, -149, -149, -149, -149, 81, 81, 81, 81,
+ -149, -149, -149, -149, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -149, -149
+
+ },
+
+ {
+ 17, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+ -150, -150, -150, -150, -150, -150, 81, 81, 81, 81,
+ -150, -150, -150, -150, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 153, 81, 81, 81, 81,
+ 81, 81, 81, 81, -150, -150
+ },
+
+ {
+ 17, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+ -151, -151, -151, -151, -151, -151, 81, 81, 81, 81,
+ -151, -151, -151, -151, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -151, -151
+
+ },
+
+ {
+ 17, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+ -152, -152, -152, -152, -152, -152, 81, 81, 81, 81,
+ -152, -152, -152, -152, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 154, 81, 81, 81, 81,
+ 81, 81, 81, 81, -152, -152
+ },
+
+ {
+ 17, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+ -153, -153, -153, -153, -153, -153, 81, 81, 81, 81,
+ -153, -153, -153, -153, 81, 81, 81, 81, 81, 155,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -153, -153
+
+ },
+
+ {
+ 17, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+ -154, -154, -154, -154, -154, -154, 81, 81, 81, 81,
+ -154, -154, -154, -154, 81, 81, 81, 81, 81, 156,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -154, -154
+ },
+
+ {
+ 17, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+ -155, -155, -155, -155, -155, -155, 81, 81, 81, 81,
+ -155, -155, -155, -155, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -155, -155
+
+ },
+
+ {
+ 17, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+ -156, -156, -156, -156, -156, -156, 81, 81, 81, 81,
+ -156, -156, -156, -156, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, -156, -156
+ },
+
+ } ;
+
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 51
+#define YY_END_OF_BUFFER 52
+static yyconst short int yy_accept[157] =
+ { 0,
+ 0, 0, 4, 4, 0, 0, 0, 0, 23, 23,
+ 27, 27, 0, 0, 0, 0, 52, 50, 1, 1,
+ 36, 2, 44, 37, 50, 43, 41, 41, 28, 3,
+ 43, 29, 4, 51, 20, 20, 19, 19, 17, 18,
+ 17, 17, 17, 17, 17, 17, 17, 22, 21, 23,
+ 26, 26, 25, 23, 27, 30, 35, 34, 31, 47,
+ 45, 46, 49, 49, 1, 36, 2, 37, 42, 43,
+ 43, 0, 41, 0, 41, 28, 3, 4, 0, 18,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 21,
+ 21, 23, 23, 25, 25, 24, 27, 30, 30, 32,
+
+ 33, 47, 0, 39, 40, 0, 17, 17, 17, 10,
+ 17, 17, 17, 17, 24, 30, 0, 39, 40, 0,
+ 17, 13, 17, 17, 17, 12, 17, 0, 0, 6,
+ 11, 17, 14, 5, 0, 0, 17, 17, 7, 17,
+ 17, 48, 38, 17, 17, 17, 17, 38, 16, 17,
+ 15, 17, 17, 17, 9, 8
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 4, 5, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 6, 7, 6, 8, 9, 1, 1, 10,
+ 11, 12, 6, 6, 13, 14, 15, 16, 17, 18,
+ 19, 19, 19, 19, 19, 19, 19, 1, 20, 1,
+ 6, 1, 6, 1, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 31, 34, 35, 31, 36, 37, 31,
+ 31, 38, 39, 40, 41, 42, 43, 31, 31, 31,
+ 21, 22, 23, 1, 24, 1, 25, 26, 27, 28,
+
+ 29, 30, 31, 32, 33, 31, 34, 35, 31, 36,
+ 37, 31, 31, 38, 39, 40, 41, 42, 43, 31,
+ 31, 31, 44, 1, 45, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "lexpgn.l"
+#define INITIAL 0
+#line 2 "lexpgn.l"
+
+/* lexpgn by David A. Wheeler (http://www.dwheeler.com).
+
+ This code processes files formatted using PGN, as defined in
+ "Standard Portable Game Notation Specification and Implementation
+ Guide" Revised 1994.03.12 by Steven J. Edwards.
+
+ This code lexically analyzes PGN files as an import format; since it's
+ importing, it tries to accept nonstandard formats as much as it can and
+ figure out the "intent". It handles varying newlines (e.g. \r), etc.
+ It will accept a great deal of misformatting that isn't,
+ strictly speaking, legal PGN, but the point is to be able to figure
+ out what was intended.
+
+ Calling the lexer will process ONE game in a file,
+ starting with 0 or more tags, followed by 0 or more moves.
+ It returns 0 if no erors, 1 if errors, 2 if terminated (normally).
+
+ It will place data somewhere depending on the value of data_dest;
+ if data_dest is DEST_TRASH, it skips the game (not fully implemented),
+ if data_dest is DEST_GAME, it stores into Game[],
+ if data_dest is DEST_BOOK, it's stored into the book material.
+ To process a multi-game PGN file, call it again and again.
+
+ Some of the funny ordering (e.g., for bracecomment) is to make it
+ high speed. Flex/lex can produce high speed lexers, but only
+ if it gets some help, in particular by defining patterns that
+ maximally match.
+
+ TODO: prevent buffer overflow for FEN.
+
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "common.h"
+#include "lexpgn.h"
+#include "book.h"
+
+
+enum tagtype { NO_TAG, EVENT_TAG, SITE_TAG, DATE_TAG, ROUND_TAG,
+ WHITE_TAG, BLACK_TAG, RESULT_TAG,
+ WHITE_ELO_TAG, BLACK_ELO_TAG,
+ WHITETITLE_TAG, BLACKTITLE_TAG, FEN_TAG,
+ OTHER_TAG };
+
+enum data_destination_t data_dest;
+
+#define yyterminate() { if ( seen_tags || seen_moves) return 1; \
+ return 2; }
+
+
+char *pgn_event;
+char *pgn_site;
+char *pgn_date;
+char *pgn_round;
+char *pgn_white;
+char *pgn_black;
+char *pgn_result;
+char *pgn_whiteELO;
+char *pgn_blackELO;
+char *pgn_othertags;
+char *initial_comments; /* PGN comments before any moves */
+
+char *return_append_str(char *dest, const char *s) {
+/* Append text s to dest, and return new result. */
+ char *newloc;
+ size_t newlen;
+ /* This doesn't have buffer overflow vulnerabilities, because
+ we always allocate for enough space before appending. */
+ if (!dest) {
+ newloc = (char *) malloc(strlen(s))+1;
+ strcpy(newloc, s);
+ return newloc;
+ }
+ newlen = strlen(dest) + strlen(s) + 1;
+ newloc = (char *) malloc(newlen);
+ strcpy(newloc, dest);
+ if (!newloc) return dest; /* Can't do it, throw away the data */
+ strcat(newloc, s);
+ return newloc;
+}
+
+void append_str(char **dest, const char *s) {
+/* Append text s to *dest, and modify *dest to new location. */
+ char *temp;
+ temp = return_append_str(*dest, s);
+ *dest = temp;
+}
+
+void append_comment(const char *t) {
+/* Append PGN text t after the current move */
+ if (data_dest == DEST_GAME) {
+ /* TODO */
+ if (GameCnt < 1) {
+ append_str(&initial_comments,t);
+ } else {
+ append_str(&(Game[GameCnt].comments),t);
+ }
+ }
+}
+
+#define tag_gobble 1
+
+#define tagsymbol 2
+
+#define tagsep 3
+
+#define tagdata 4
+
+#define tagend 5
+
+#define bracecomment 6
+
+#define RAV 7
+
+#line 1825 "lexpgn.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ yy_current_buffer->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp = NULL, *yy_bp = NULL;
+ register int yy_act;
+
+#line 129 "lexpgn.l"
+
+ /* These are executed on each entry to the code */
+ int seen_tags = 0;
+ int seen_moves = 0;
+ enum tagtype ctag = NO_TAG;
+ int firstmovenum = -1;
+ int side = white;
+ int rav_count = 0;
+ int result = R_NORESULT;
+ char tagname[80]; /* Name of tag currently being processed */
+ leaf *p;
+ int addtobook[2];
+ addtobook[0] = 0;
+ addtobook[1] = 0;
+
+
+#line 1983 "lexpgn.c"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ while ( (yy_current_state = yy_nxt[yy_current_state][yy_ec[YY_SC_TO_UI(*yy_cp)]]) > 0 )
+ {
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+
+ ++yy_cp;
+ }
+
+ yy_current_state = -yy_current_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos + 1;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 145 "lexpgn.l"
+{ /* Ignore whitespace */ }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 146 "lexpgn.l"
+{ /* Ignore PGN escape. We'll allow initial space. */ }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 148 "lexpgn.l"
+{
+ /* Handle "[". If we've already seen a move, return "[" to
+ the stream and return. */
+ /* We rashly match on any SC to avoid trouble with unmatched
+ brackets of various types */
+ seen_tags = 1;
+ ctag = NO_TAG;
+ if (seen_moves) {
+ BEGIN(INITIAL);
+ yyless(0); /* put the "[" back. */
+ return 0;
+ }
+ if (data_dest == DEST_TRASH) {BEGIN(tag_gobble);}
+ else { BEGIN(tagsymbol); }
+ }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 165 "lexpgn.l"
+{BEGIN(INITIAL);}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 167 "lexpgn.l"
+{ctag = WHITE_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 168 "lexpgn.l"
+{ctag = BLACK_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 169 "lexpgn.l"
+{ctag = RESULT_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 170 "lexpgn.l"
+{ctag = WHITETITLE_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 171 "lexpgn.l"
+{ctag = BLACKTITLE_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 172 "lexpgn.l"
+{ctag = FEN_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 173 "lexpgn.l"
+{ctag = EVENT_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 174 "lexpgn.l"
+{ctag = SITE_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 175 "lexpgn.l"
+{ctag = DATE_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 176 "lexpgn.l"
+{ctag = ROUND_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 177 "lexpgn.l"
+{ctag = WHITE_ELO_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 178 "lexpgn.l"
+{ctag = BLACK_ELO_TAG; BEGIN(tagsep);}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 179 "lexpgn.l"
+{
+ ctag = OTHER_TAG;
+ if (yyleng >= (sizeof(tagname)-1)) {
+ printf("Error, tagname too long: %s", yytext);
+ return 1;
+ }
+ strncpy(tagname, yytext, sizeof(tagname)-1);
+ BEGIN(tagsep);
+ }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 188 "lexpgn.l"
+{BEGIN(INITIAL); /* No tag name, skip. */}
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 189 "lexpgn.l"
+{BEGIN(INITIAL); /* Line ended early. */}
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 190 "lexpgn.l"
+{
+ printf("Bad character as tag name: %s\n", yytext);
+ return 1;
+ }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 195 "lexpgn.l"
+{BEGIN(tagdata);}
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 196 "lexpgn.l"
+{
+ printf("Bad character as tag separator: %s\n", yytext);
+ return 1;
+ }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 201 "lexpgn.l"
+{ /* tag data */
+
+ /* We start at first " in tag, and must match
+ till we reach an unprotected " or end of line */
+
+ BEGIN(tagend);
+ /* TODO: if DEST_GAME, store tag symbol and data for later saving */
+ switch(ctag) {
+ case WHITE_TAG:
+ /* printf("White = %s\n", yytext); */
+ if ((data_dest == DEST_BOOK) &&
+ IsTrustedPlayer(yytext)) addtobook[white]=1;
+ if (data_dest == DEST_GAME)
+ pgn_white = strdup(yytext);
+ break;
+ case BLACK_TAG:
+ /* printf("Black = %s\n", yytext); */
+ if ((data_dest == DEST_BOOK) &&
+ IsTrustedPlayer(yytext)) addtobook[black]=1;
+ if (data_dest == DEST_GAME)
+ pgn_black = strdup(yytext);
+ break;
+ case RESULT_TAG:
+ /* printf("Result = %s\n", yytext); */
+ if (!strcmp(yytext, "1-0")) result = R_WHITE_WINS;
+ else if (!strcmp(yytext, "0-1")) result = R_BLACK_WINS;
+ else if (!strcmp(yytext, "1/2-1/2"))
+ result = R_DRAW;
+ if (data_dest == DEST_GAME)
+ pgn_result = strdup(yytext);
+ break;
+ case WHITETITLE_TAG: /* We'll trust GM, IM, FMs */
+ if (data_dest == DEST_BOOK &&
+ (strcmp(yytext, "GM") == 0 ||
+ strcmp(yytext, "IM") == 0 ||
+ strcmp(yytext, "FM") == 0))
+ addtobook[white]=1;
+ if (data_dest == DEST_GAME) {
+ append_str(&pgn_othertags, "[WhiteTitle \"");
+ append_str(&pgn_othertags, yytext);
+ append_str(&pgn_othertags, "\"]\n");
+ }
+ break;
+ case BLACKTITLE_TAG:
+ if (data_dest == DEST_BOOK &&
+ (strcmp(yytext, "GM") == 0 ||
+ strcmp(yytext, "IM") == 0 ||
+ strcmp(yytext, "FM") == 0))
+ addtobook[black]=1;
+ if (data_dest == DEST_GAME) {
+ append_str(&pgn_othertags, "[BlackTitle \"");
+ append_str(&pgn_othertags, yytext);
+ append_str(&pgn_othertags, "\"]\n");
+ }
+ break;
+ case FEN_TAG:
+ /* Legal FEN is no more than 81 chars long, because
+ 71 (a character for every board cell, plus
+ separators) + 1 (space) + 1 (side, w or b) +
+ 1 (space) + 4 (castling, KQkq) + 1 (space) +
+ 2 (en passant) = 71. We'll leave one char
+ for miscount/whitespace. This doesn't fully
+ protect against buffer overflow attacks; the
+ parsing routine still has to check to make sure
+ its input don't force it to walk off the end
+ of any arrays. Still, it helps as a sanity check. */
+ /* printf("FEN tag encountered \"%s\"\n",yytext); */
+ if (yyleng > 82) {
+ printf("Error: FEN too long: %s\n", yytext);
+ return 1;
+ }
+ /* Doesn't return failure/success; just
+ do the best you can */
+ ParseEPD(yytext);
+ /* Remember it can be black to move now */
+ side = board.side;
+ if (data_dest == DEST_GAME) {
+ append_str(&pgn_othertags, "[FEN \"");
+ append_str(&pgn_othertags, yytext);
+ append_str(&pgn_othertags, "\"]\n");
+ }
+ break;
+ case EVENT_TAG:
+ if (data_dest == DEST_GAME)
+ pgn_event = strdup(yytext);
+ break;
+ case SITE_TAG:
+ if (data_dest == DEST_GAME)
+ pgn_site = strdup(yytext);
+ break;
+ case DATE_TAG:
+ if (data_dest == DEST_GAME)
+ pgn_date = strdup(yytext);
+ break;
+ case ROUND_TAG:
+ if (data_dest == DEST_GAME)
+ pgn_round = strdup(yytext);
+ break;
+ case WHITE_ELO_TAG:
+ if (data_dest == DEST_GAME)
+ pgn_whiteELO = strdup(yytext);
+ break;
+ case BLACK_ELO_TAG:
+ if (data_dest == DEST_GAME)
+ pgn_blackELO = strdup(yytext);
+ break;
+ case NO_TAG:
+ case OTHER_TAG:
+ if (data_dest == DEST_GAME) {
+ append_str(&pgn_othertags, "[");
+ append_str(&pgn_othertags, tagname);
+ append_str(&pgn_othertags, " \"");
+ append_str(&pgn_othertags, yytext);
+ append_str(&pgn_othertags, "\"]\n");
+ }
+ break;
+ }
+ }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 319 "lexpgn.l"
+{BEGIN(INITIAL);}
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 320 "lexpgn.l"
+{BEGIN(INITIAL); /* Garbage, do what can. */}
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 321 "lexpgn.l"
+{BEGIN(INITIAL); /* End-of-line. */}
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 323 "lexpgn.l"
+{BEGIN(INITIAL); /* Consume leftover */}
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 325 "lexpgn.l"
+{ /* PGN comment */
+ seen_moves = 1;
+ append_comment(yytext);
+ append_comment("\n");
+ }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 331 "lexpgn.l"
+{ /* PGN comment */
+ seen_moves = 1;
+ append_comment(yytext);
+ BEGIN(bracecomment);
+ }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 336 "lexpgn.l"
+{ /* PGN comment; may embed \n */
+ append_comment(yytext);
+ }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 339 "lexpgn.l"
+{
+ append_comment(yytext);
+ BEGIN(INITIAL);
+ }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 343 "lexpgn.l"
+{ append_comment("\n"); }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 344 "lexpgn.l"
+{ append_comment("\n"); }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 345 "lexpgn.l"
+{ append_comment("\n"); }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 346 "lexpgn.l"
+{ append_comment("\n"); }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 349 "lexpgn.l"
+{ seen_moves = 1; /* Numeric Annotation Glyph */
+ append_comment(yytext);
+ }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 353 "lexpgn.l"
+{ return 0; /* could check if consistent w/Result */ }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 354 "lexpgn.l"
+{ return 0; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 355 "lexpgn.l"
+{ return 0; }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 356 "lexpgn.l"
+{ return 0; }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 358 "lexpgn.l"
+{ seen_moves = 1; /* Move number */
+ if (firstmovenum == -1) {
+ /* TODO: Use this info somehow */
+ sscanf(yytext, "%d", &firstmovenum);
+ if (firstmovenum < 0 || firstmovenum > 32000)
+ firstmovenum = -1;
+ /* printf("First move num=%d\n", firstmovenum); */
+ }
+ }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 368 "lexpgn.l"
+{ seen_moves = 1; side = black; }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 371 "lexpgn.l"
+{ /* Process a move */
+ seen_moves = 1;
+ if (data_dest != DEST_TRASH) {
+ /* printf("Seen move %s\n", yytext); */
+ /* SAN moves can be at most 7 characters, and
+ Game[].SANmv must be able to store the result. */
+ if (yyleng > 7) {
+ printf("Error: move too long: %s\n", yytext);
+ return 1;
+ }
+ p = ValidateMove(yytext);
+ if (!p) {
+ printf ("Illegal move: %s\n", yytext);
+ return 1;
+ }
+ /* MakeMove increments GameCnt */
+ MakeMove(side, &p->move);
+ if (addtobook[side]) {
+ if (BookBuilder (result, side) == BOOK_EFULL) {
+ printf("Book full - Failed to add move %s\n",
+ yytext);
+ ShowBoard();
+ return 1;
+ }
+
+ }
+ strcpy(Game[GameCnt].SANmv, yytext);
+ side = 1^side;
+ }
+ }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 402 "lexpgn.l"
+{ rav_count = 1; append_comment(yytext); BEGIN(RAV); }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 403 "lexpgn.l"
+{ rav_count++; append_comment(yytext); }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 404 "lexpgn.l"
+{ rav_count--; append_comment(yytext);
+ if (rav_count <=0) BEGIN(INITIAL); }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 406 "lexpgn.l"
+{ append_comment(yytext);
+ /* We escape [ to avoid problems with
+ unclosed RAV */
+ }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 410 "lexpgn.l"
+{ yyless(0) ; BEGIN(INITIAL); return(0) ; /* Damn humans */}
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 411 "lexpgn.l"
+{ append_comment(yytext); }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 414 "lexpgn.l"
+{
+ printf("Illegal character %c in input stream.\n", yytext[0]);
+ return 1;
+ }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 419 "lexpgn.l"
+ECHO;
+ YY_BREAK
+#line 2513 "lexpgn.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(tag_gobble):
+case YY_STATE_EOF(tagsymbol):
+case YY_STATE_EOF(tagsep):
+case YY_STATE_EOF(tagdata):
+case YY_STATE_EOF(tagend):
+case YY_STATE_EOF(bracecomment):
+case YY_STATE_EOF(RAV):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ yy_current_state = yy_nxt[yy_current_state][1];
+ yy_is_jam = (yy_current_state <= 0);
+
+ if ( ! yy_is_jam )
+ {
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ }
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+ yy_current_buffer->yy_at_bol = (c == '\n');
+
+ return c;
+ }
+#endif /* YY_NO_INPUT */
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 419 "lexpgn.l"
+
+
diff --git a/src/chess_computer-activity/gnuchess/lexpgn.h b/src/chess_computer-activity/gnuchess/lexpgn.h
new file mode 100644
index 0000000..91ead55
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/lexpgn.h
@@ -0,0 +1,27 @@
+#ifndef LEXPGNX_H
+
+#define LEXPGNX_H
+
+/* lexpgnx.h - This header file defines the types and global variables
+ * exported from the generated lexpgn file to others.
+ * It's named "lexpgnx" and not "lexpgn", because some lex-like program
+ * might automatically generate a file named lexpgn.h and we don't
+ * want this file to be overwritten.
+ */
+
+enum data_destination_t { DEST_TRASH, DEST_GAME, DEST_BOOK };
+extern enum data_destination_t data_dest;
+
+extern char *initial_comments;
+extern char *pgn_event;
+extern char *pgn_site;
+extern char *pgn_date;
+extern char *pgn_round;
+extern char *pgn_white;
+extern char *pgn_black;
+extern char *pgn_whiteELO;
+extern char *pgn_blackELO;
+extern char *pgn_result;
+extern char *pgn_othertags;
+
+#endif
diff --git a/src/chess_computer-activity/gnuchess/main.c b/src/chess_computer-activity/gnuchess/main.c
new file mode 100644
index 0000000..f13120b
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/main.c
@@ -0,0 +1,471 @@
+/* GNU Chess 5.0 - main.c - entry point
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "common.h"
+#include "book.h"
+
+short distance[64][64];
+short taxicab[64][64];
+unsigned char lzArray[65536];
+BitBoard DistMap[64][8];
+BitBoard BitPosArray[64];
+BitBoard NotBitPosArray[64];
+BitBoard MoveArray[8][64];
+BitBoard Ray[64][8];
+BitBoard FromToRay[64][64];
+BitBoard RankBit[8];
+BitBoard FileBit[8];
+BitBoard Ataks[2][7];
+BitBoard PassedPawnMask[2][64];
+BitBoard IsolaniMask[8];
+BitBoard SquarePawnMask[2][64];
+BitBoard Rook00Atak[64][256];
+BitBoard Rook90Atak[64][256];
+BitBoard Bishop45Atak[64][256];
+BitBoard Bishop315Atak[64][256];
+BitBoard pinned;
+BitBoard rings[4];
+BitBoard boxes[2];
+BitBoard stonewall[2];
+BitBoard pieces[2];
+BitBoard mask_kr_trapped_w[3];
+BitBoard mask_kr_trapped_b[3];
+BitBoard mask_qr_trapped_w[3];
+BitBoard mask_qr_trapped_b[3];
+BitBoard boardhalf[2];
+BitBoard boardside[2];
+short directions[64][64];
+unsigned char BitCount[65536];
+leaf Tree[MAXTREEDEPTH];
+leaf *TreePtr[MAXPLYDEPTH];
+int RootPV;
+GameRec Game[MAXGAMEDEPTH];
+int GameCnt;
+int RealGameCnt;
+short RealSide;
+int computer;
+unsigned int flags;
+unsigned int preanalyze_flags;
+int cboard[64];
+int Mvboard[64];
+Board board;
+HashType hashcode[2][7][64];
+HashType ephash[64];
+HashType WKCastlehash;
+HashType WQCastlehash;
+HashType BKCastlehash;
+HashType BQCastlehash;
+HashType Sidehash;
+HashType HashKey;
+HashType PawnHashKey;
+HashSlot *HashTab[2];
+PawnSlot *PawnTab[2];
+int Idepth;
+int SxDec;
+int Game50;
+int lazyscore[2];
+int maxposnscore[2];
+int rootscore;
+int lastrootscore;
+unsigned long GenCnt;
+unsigned long NodeCnt;
+unsigned long QuiesCnt;
+unsigned long EvalCnt;
+unsigned long EvalCall;
+unsigned long ChkExtCnt;
+unsigned long OneRepCnt;
+unsigned long RcpExtCnt;
+unsigned long PawnExtCnt;
+unsigned long HorzExtCnt;
+unsigned long ThrtExtCnt;
+unsigned long KingExtCnt;
+unsigned long NullCutCnt;
+unsigned long FutlCutCnt;
+unsigned long RazrCutCnt;
+unsigned long TotalGetHashCnt;
+unsigned long GoodGetHashCnt;
+unsigned long TotalPutHashCnt;
+unsigned long CollHashCnt;
+unsigned long TotalPawnHashCnt;
+unsigned long GoodPawnHashCnt;
+unsigned long RepeatCnt;
+unsigned HashSize;
+unsigned long TTHashMask;
+unsigned long PHashMask;
+char SANmv[SANSZ];
+unsigned long history[2][4096];
+int killer1[MAXPLYDEPTH];
+int killer2[MAXPLYDEPTH];
+int ChkCnt[MAXPLYDEPTH];
+int ThrtCnt[MAXPLYDEPTH];
+char id[32];
+char solution[64];
+double ElapsedTime;
+Timer StartTime;
+float SearchTime;
+int SearchDepth;
+int MoveLimit[2];
+float TimeLimit[2];
+int TCMove;
+int TCinc;
+float TCTime;
+int castled[2];
+int hunged[2];
+int phase;
+int Hashmv[MAXPLYDEPTH];
+short RootPieces;
+short RootPawns;
+short RootMaterial;
+short RootAlpha;
+short RootBeta;
+short pickphase[MAXPLYDEPTH];
+short InChk[MAXPLYDEPTH];
+short KingThrt[2][MAXPLYDEPTH];
+short threatmv;
+uint8_t threatply;
+short KingSafety[2];
+short pscore[64];
+short bookmode;
+short bookfirstlast;
+
+char *progname;
+FILE *ofp;
+int myrating, opprating, suddendeath, TCionc;
+char name[50];
+int computerplays; /* Side computer is playing */
+int wasbookmove; /* True if last move was book move */
+int nmovesfrombook; /* Number of moves since last book move */
+int newpos, existpos; /* For book statistics */
+float maxtime; /* Max time for the next searched move */
+int n; /* Last mobility returned by CTL */
+int ExchCnt[2]; /* How many exchanges? */
+int bookloaded = 0; /* Is the book loaded already into memory? */
+
+int slider[8] = { 0, 0, 0, 1, 1, 1, 0, 0 };
+int Value[7] = { 0, ValueP, ValueN, ValueB, ValueR, ValueQ, ValueK};
+int range[8] = { 0, 0, 0, 1, 1, 1, 0, 0 };
+int ptype[2] = { pawn, bpawn };
+char algbr[64][3] =
+{ "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
+ "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
+ "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
+ "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
+ "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
+ "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
+ "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
+ "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"
+};
+char algbrfile[9] = "abcdefgh";
+char algbrrank[9] = "12345678";
+
+char notation[8] = { " PNBRQK" };
+char lnotation[8] = { " pnbrqk" };
+
+short Shift00[64] =
+{ 56, 56, 56, 56, 56, 56, 56, 56,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 40, 40, 40, 40, 40, 40, 40, 40,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 24, 24, 24, 24, 24, 24, 24, 24,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+int r90[64] =
+{ A8, A7, A6, A5, A4, A3, A2, A1,
+ B8, B7, B6, B5, B4, B3, B2, B1,
+ C8, C7, C6, C5, C4, C3, C2, C1,
+ D8, D7, D6, D5, D4, D3, D2, D1,
+ E8, E7, E6, E5, E4, E3, E2, E1,
+ F8, F7, F6, F5, F4, F3, F2, F1,
+ G8, G7, G6, G5, G4, G3, G2, G1,
+ H8, H7, H6, H5, H4, H3, H2, H1 };
+
+short Shift90[64] =
+{ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 0, 8, 16, 24, 32, 40, 48, 56
+};
+
+int r45[64] =
+{ E4, F3, H2, C2, G1, D1, B1, A1,
+ E5, F4, G3, A3, D2, H1, E1, C1,
+ D6, F5, G4, H3, B3, E2, A2, F1,
+ B7, E6, G5, H4, A4, C3, F2, B2,
+ G7, C7, F6, H5, A5, B4, D3, G2,
+ C8, H7, D7, G6, A6, B5, C4, E3,
+ F8, D8, A8, E7, H6, B6, C5, D4,
+ H8, G8, E8, B8, F7, A7, C6, D5 };
+
+short Shift45[64] =
+{ 28, 36, 43, 49, 54, 58, 61, 63,
+ 21, 28, 36, 43, 49, 54, 58, 61,
+ 15, 21, 28, 36, 43, 49, 54, 58,
+ 10, 15, 21, 28, 36, 43, 49, 54,
+ 6, 10, 15, 21, 28, 36, 43, 49,
+ 3, 6, 10, 15, 21, 28, 36, 43,
+ 1, 3, 6, 10, 15, 21, 28, 36,
+ 0, 1, 3, 6, 10, 15, 21, 28 };
+
+int Mask45[64] =
+{ 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01,
+ 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03,
+ 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07,
+ 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+ 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F,
+ 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F,
+ 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F,
+ 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
+
+int r315[64] =
+{ A1, C1, F1, B2, G2, E3, D4, D5,
+ B1, E1, A2, F2, D3, C4, C5, C6,
+ D1, H1, E2, C3, B4, B5, B6, A7,
+ G1, D2, B3, A4, A5, A6, H6, F7,
+ C2, A3, H3, H4, H5, G6, E7, B8,
+ H2, G3, G4, G5, F6, D7, A8, E8,
+ F3, F4, F5, E6, C7, H7, D8, G8,
+ E4, E5, D6, B7, G7, C8, F8, H8 };
+
+short Shift315[64] =
+{ 63, 61, 58, 54, 49, 43, 36, 28,
+ 61, 58, 54, 49, 43, 36, 28, 21,
+ 58, 54, 49, 43, 36, 28, 21, 15,
+ 54, 49, 43, 36, 28, 21, 15, 10,
+ 49, 43, 36, 28, 21, 15, 10, 6,
+ 43, 36, 28, 21, 15, 10, 6, 3,
+ 36, 28, 21, 15, 10, 6, 3, 1,
+ 28, 21, 15, 10, 6, 3, 1, 0 };
+
+int Mask315[64] =
+{ 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,
+ 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F,
+ 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F,
+ 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F,
+ 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+ 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07,
+ 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03,
+ 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
+
+int rank6[2] = { 5, 2 };
+int rank7[2] = { 6, 1 };
+int rank8[2] = { 7, 0 };
+
+int main (int argc, char *argv[])
+{
+ int i;
+
+ /*
+ * Parse command line arguments conforming with getopt_long syntax
+ * Note: we have to support "xboard" and "post" as bare strings
+ * for backward compatibility.
+ */
+
+ int c;
+ int opt_help = 0, opt_version = 0, opt_post = 0, opt_xboard = 0, opt_hash = 0, opt_easy = 0, opt_manual = 0;
+ char *endptr;
+
+ progname = argv[0]; /* Save in global for cmd_usage */
+
+ while (1)
+ {
+ static struct option long_options[] =
+ {
+ {"hashsize", 1, 0, 's'},
+ {"version", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {"xboard", 0, 0, 'x'},
+ {"post", 0, 0, 'p'},
+ {"easy", 0, 0, 'e'},
+ {"manual", 0, 0, 'm'},
+ {0, 0, 0, 0}
+ };
+
+ /* getopt_long stores the option index here. */
+
+ int option_index = 0;
+
+ c = getopt_long (argc, argv, "ehmpvxs:",
+ long_options, &option_index);
+
+ /* Detect the end of the options. */
+ if (c == -1)
+ break;
+
+ /*
+ * Options with a straight flag, could use getoopt_long
+ * flag setting but this is more "obvious" and easier to
+ * modify.
+ */
+ switch (c)
+ {
+ case 'v':
+ opt_version = 1;
+ break;
+ case 'h':
+ opt_help = 1;
+ break;
+ case 'x':
+ opt_xboard = 1;
+ break;
+ case 'p':
+ opt_post = 1;
+ break;
+ case 'e':
+ opt_easy = 1;
+ break;
+ case 'm':
+ opt_manual = 1;
+ break;
+ case 's':
+ if ( optarg == NULL ){ /* we have error such as two -s */
+ opt_help = 1;
+ break;
+ }
+ errno = 0; /* zero error indicator */
+ opt_hash = strtol (optarg, &endptr, 10);
+ if ( errno != 0 || *endptr != '\0' ){
+ printf("Hashsize out of Range or Invalid\n");
+ return(1);
+ }
+ break;
+ case '?': /* On error give help - getopt does a basic message. */
+ opt_help = 1;
+ break;
+ default:
+ puts ("Option Processing Failed\n");
+ abort();
+ }
+ } /* end of getopt_long style parsing */
+
+ /* Initialize random number generator */
+ srand((unsigned int) time(NULL));
+
+ /* initialize control flags */
+ flags = ULL(0);
+
+ /* output for thinking */
+ ofp = stdout;
+
+ /* Handle old style command line options */
+ if (argc > 1) {
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i],"xboard") == 0) {
+ SET (flags, XBOARD);
+ } else if (strcmp(argv[i],"post") == 0) {
+ SET (flags, POST);
+ }
+ }
+ }
+ if (opt_xboard == 1)
+ SET (flags, XBOARD);
+ if (opt_post == 1)
+ SET (flags, POST);
+ if (opt_manual ==1)
+ SET (flags, MANUAL);
+ cmd_version();
+
+ /* If the version option was specified we can exit here */
+ if (opt_version == 1)
+ return(0);
+
+ /* If a usage statement is required output it here */
+ if (opt_help == 1){
+ cmd_usage();
+ return (1); /* Maybe an error if due to bad arguments. */
+ }
+
+ dbg_open(NULL);
+
+ HashSize = 0 ; /* Set HashSize zero */
+ if ( opt_hash != 0)
+ CalcHashSize(opt_hash);
+
+ Initialize ();
+
+ if ( opt_easy == 0)
+ SET (flags, HARD);
+
+ if (argc > 1) {
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i],"xboard") == 0) {
+ SET (flags, XBOARD);
+ } else if (strcmp(argv[i],"post") == 0) {
+ SET (flags, POST);
+ }
+ }
+ }
+
+ bookmode = BOOKPREFER;
+ bookfirstlast = 3;
+
+ while (!(flags & QUIT)) {
+ dbg_printf("Waiting for input...\n");
+ wait_for_input();
+ dbg_printf("Parsing input...\n");
+ parse_input();
+ dbg_printf("input_status = %d\n", input_status);
+ if ((flags & THINK) && !(flags & MANUAL) && !(flags & ENDED)) {
+ if (!(flags & XBOARD)) printf("Thinking...\n");
+ Iterate ();
+ CLEAR (flags, THINK);
+ }
+ RealGameCnt = GameCnt;
+ RealSide = board.side;
+ dbg_printf("Waking up input...\n");
+ dbg_printf("input_status = %d\n", input_status);
+ input_wakeup();
+ dbg_printf("input_status = %d\n", input_status);
+ /* Ponder only after first move */
+ /* Ponder or (if pondering disabled) just wait for input */
+ if ((flags & HARD) && !(flags & QUIT) ) {
+ ponder();
+ }
+ }
+
+ CleanupInput();
+
+ /* Some cleaning up */
+ free (HashTab[0]);
+ free (HashTab[1]);
+
+ dbg_close();
+ return (0);
+}
diff --git a/src/chess_computer-activity/gnuchess/move.c b/src/chess_computer-activity/gnuchess/move.c
new file mode 100644
index 0000000..02ee1a4
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/move.c
@@ -0,0 +1,939 @@
+/* GNU Chess 5.0 - move.c - make and unmake moves code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "common.h"
+
+void MakeMove (int side, int *move)
+/**************************************************************************
+ *
+ * To make a move on the board and update the various game information.
+ *
+ **************************************************************************/
+{
+ BitBoard *a;
+ int f, t, fpiece, tpiece;
+ int rookf, rookt, epsq, sq;
+ int xside;
+ GameRec *g;
+
+ xside = 1^side;
+ f = FROMSQ(*move);
+ t = TOSQ(*move);
+ fpiece = cboard[f];
+ tpiece = cboard[t];
+ a = &board.b[side][fpiece];
+ CLEARBIT (*a, f);
+ SETBIT (*a, t);
+ CLEARBIT (board.blockerr90, r90[f]);
+ SETBIT (board.blockerr90, r90[t]);
+ CLEARBIT (board.blockerr45, r45[f]);
+ SETBIT (board.blockerr45, r45[t]);
+ CLEARBIT (board.blockerr315, r315[f]);
+ SETBIT (board.blockerr315, r315[t]);
+ cboard[f] = empty;
+ cboard[t] = fpiece;
+ GameCnt++;
+ g = &Game[GameCnt];
+ g->epsq = board.ep;
+ g->bflag = board.flag;
+ g->Game50 = Game50;
+ g->hashkey = HashKey;
+ g->phashkey = PawnHashKey;
+ g->mvboard = Mvboard[t];
+ g->comments = NULL;
+ Mvboard[t] = Mvboard[f]+1;
+ Mvboard[f] = 0;
+ if (board.ep > -1)
+ HashKey ^= ephash[board.ep];
+ HashKey ^= hashcode[side][fpiece][f];
+ HashKey ^= hashcode[side][fpiece][t];
+ if (fpiece == king)
+ board.king[side] = t;
+ if (fpiece == pawn)
+ {
+ PawnHashKey ^= hashcode[side][pawn][f];
+ PawnHashKey ^= hashcode[side][pawn][t];
+ }
+
+ if (tpiece != 0) /* Capture */
+ {
+ ExchCnt[side]++;
+ CLEARBIT (board.b[xside][tpiece], t);
+ *move |= (tpiece << 15);
+ HashKey ^= hashcode[xside][tpiece][t];
+ if (tpiece == pawn)
+ PawnHashKey ^= hashcode[xside][pawn][t];
+ board.material[xside] -= Value[tpiece];
+ if (tpiece != pawn)
+ board.pmaterial[xside] -= Value[tpiece];
+ }
+
+ if (*move & PROMOTION) /* Promotion */
+ {
+ SETBIT (board.b[side][PROMOTEPIECE (*move)], t);
+ CLEARBIT (*a, t);
+ cboard[t] = PROMOTEPIECE (*move);
+ HashKey ^= hashcode[side][pawn][t];
+ HashKey ^= hashcode[side][cboard[t]][t];
+ PawnHashKey ^= hashcode[side][pawn][t];
+ board.material[side] += (Value[cboard[t]] - ValueP);
+ board.pmaterial[side] += Value[cboard[t]];
+ }
+
+ if (*move & ENPASSANT) /* En passant */
+ {
+ ExchCnt[side]++;
+ epsq = board.ep + (side == white ? - 8 : 8);
+ CLEARBIT (board.b[xside][pawn], epsq);
+ CLEARBIT (board.blockerr90, r90[epsq]);
+ CLEARBIT (board.blockerr45, r45[epsq]);
+ CLEARBIT (board.blockerr315, r315[epsq]);
+ cboard[epsq] = empty;
+ HashKey ^= hashcode[xside][pawn][epsq];
+ PawnHashKey ^= hashcode[xside][pawn][epsq];
+ board.material[xside] -= ValueP;
+ }
+ if (*move & (CAPTURE | CASTLING) || fpiece == pawn)
+ Game50 = GameCnt;
+
+ if (*move & CASTLING) /* Castling */
+ {
+ if (t & 0x04) /* King side */
+ {
+ rookf = t + 1;
+ rookt = t - 1;
+ }
+ else /* Queen side */
+ {
+ rookf = t - 2;
+ rookt = t + 1;
+ }
+ a = &board.b[side][rook];
+ CLEARBIT (*a, rookf);
+ SETBIT (*a, rookt);
+ CLEARBIT (board.blockerr90, r90[rookf]);
+ SETBIT (board.blockerr90, r90[rookt]);
+ CLEARBIT (board.blockerr45, r45[rookf]);
+ SETBIT (board.blockerr45, r45[rookt]);
+ CLEARBIT (board.blockerr315, r315[rookf]);
+ SETBIT (board.blockerr315, r315[rookt]);
+ cboard[rookf] = empty;
+ cboard[rookt] = rook;
+ Mvboard[rookf] = 0;
+ Mvboard[rookt] = 1;
+ HashKey ^= hashcode[side][rook][rookf];
+ HashKey ^= hashcode[side][rook][rookt];
+ board.castled[side] = true;
+ }
+
+ /* If king or rook move, clear castle flag. */
+ if (side == white)
+ {
+ if (fpiece == king && board.flag & WCASTLE)
+ {
+ if (board.flag & WKINGCASTLE)
+ HashKey ^= WKCastlehash;
+ if (board.flag & WQUEENCASTLE)
+ HashKey ^= WQCastlehash;
+ board.flag &= ~WCASTLE;
+ }
+ else if (fpiece == rook)
+ {
+ if (f == H1)
+ {
+ if (board.flag & WKINGCASTLE)
+ HashKey ^= WKCastlehash;
+ board.flag &= ~WKINGCASTLE;
+ }
+ else if (f == A1)
+ {
+ if (board.flag & WQUEENCASTLE)
+ HashKey ^= WQCastlehash;
+ board.flag &= ~WQUEENCASTLE;
+ }
+ }
+ if (tpiece == rook)
+ {
+ if (t == H8)
+ {
+ if (board.flag & BKINGCASTLE)
+ HashKey ^= BKCastlehash;
+ board.flag &= ~BKINGCASTLE;
+ }
+ else if (t == A8)
+ {
+ if (board.flag & BQUEENCASTLE)
+ HashKey ^= BQCastlehash;
+ board.flag &= ~BQUEENCASTLE;
+ }
+ }
+ }
+ else
+ {
+ if (fpiece == king && board.flag & BCASTLE)
+ {
+ if (board.flag & BKINGCASTLE)
+ HashKey ^= BKCastlehash;
+ if (board.flag & BQUEENCASTLE)
+ HashKey ^= BQCastlehash;
+ board.flag &= ~BCASTLE;
+ }
+ else if (fpiece == rook)
+ {
+ if (f == H8)
+ {
+ if (board.flag & BKINGCASTLE)
+ HashKey ^= BKCastlehash;
+ board.flag &= ~BKINGCASTLE;
+ }
+ else if (f == A8)
+ {
+ if (board.flag & BQUEENCASTLE)
+ HashKey ^= BQCastlehash;
+ board.flag &= ~BQUEENCASTLE;
+ }
+ }
+ if (tpiece == rook)
+ {
+ if (t == H1)
+ {
+ if (board.flag & WKINGCASTLE)
+ HashKey ^= WKCastlehash;
+ board.flag &= ~WKINGCASTLE;
+ }
+ else if (t == A1)
+ {
+ if (board.flag & WQUEENCASTLE)
+ HashKey ^= WQCastlehash;
+ board.flag &= ~WQUEENCASTLE;
+ }
+ }
+ }
+
+
+ /* If pawn move 2 squares, set ep passant square. */
+ if (fpiece == pawn && abs(f-t) == 16)
+ {
+ sq = (f + t) / 2;
+ board.ep = sq;
+ HashKey ^= ephash[sq];
+ }
+ else
+ board.ep = -1;
+
+ board.side = xside;
+ HashKey ^= Sidehash;
+ UpdateFriends ();
+
+ /* Update game record */
+ g->move = *move;
+ return;
+}
+
+
+
+void UnmakeMove (int side, int *move)
+/****************************************************************************
+ *
+ * To unmake a move on the board and update the various game information.
+ * Note that if side is black, then black is about to move, but we will be
+ * undoing a move by white, not black.
+ *
+ ****************************************************************************/
+{
+ BitBoard *a;
+ int f, t, fpiece, cpiece;
+ int rookf, rookt, epsq;
+ int xside;
+ GameRec *g;
+
+ side = 1^side;
+ xside = 1^side;
+ f = FROMSQ(*move);
+ t = TOSQ(*move);
+ fpiece = cboard[t];
+ cpiece = CAPTUREPIECE (*move);
+ a = &board.b[side][fpiece];
+ CLEARBIT (*a, t);
+ SETBIT (*a, f);
+ CLEARBIT (board.blockerr90, r90[t]);
+ SETBIT (board.blockerr90, r90[f]);
+ CLEARBIT (board.blockerr45, r45[t]);
+ SETBIT (board.blockerr45, r45[f]);
+ CLEARBIT (board.blockerr315, r315[t]);
+ SETBIT (board.blockerr315, r315[f]);
+ cboard[f] = cboard[t];
+ cboard[t] = empty;
+ g = &Game[GameCnt];
+ Mvboard[f] = Mvboard[t]-1;
+ Mvboard[t] = g->mvboard;
+ if (fpiece == king)
+ board.king[side] = f;
+
+ /* if capture, put back the captured piece */
+ if (*move & CAPTURE)
+ {
+ ExchCnt[side]--;
+ SETBIT (board.b[xside][cpiece], t);
+ SETBIT (board.blockerr90, r90[t]);
+ SETBIT (board.blockerr45, r45[t]);
+ SETBIT (board.blockerr315, r315[t]);
+ cboard[t] = cpiece;
+ board.material[xside] += Value[cpiece];
+ if (cpiece != pawn)
+ board.pmaterial[xside] += Value[cpiece];
+ }
+
+ /* Undo promotion */
+ if (*move & PROMOTION)
+ {
+ CLEARBIT (*a, f);
+ SETBIT (board.b[side][pawn], f);
+ cboard[f] = pawn;
+ board.material[side] += (ValueP - Value[PROMOTEPIECE (*move)]);
+ board.pmaterial[side] -= Value[PROMOTEPIECE (*move)];
+ }
+
+ /* Undo enpassant */
+ if (*move & ENPASSANT)
+ {
+ ExchCnt[side]--;
+ epsq = (side == white ? g->epsq - 8 : g->epsq + 8);
+ SETBIT (board.b[xside][pawn], epsq);
+ SETBIT (board.blockerr90, r90[epsq]);
+ SETBIT (board.blockerr45, r45[epsq]);
+ SETBIT (board.blockerr315, r315[epsq]);
+ cboard[epsq] = pawn;
+ board.material[xside] += ValueP;
+ }
+
+ /* if castling, undo rook move */
+ if (*move & CASTLING)
+ {
+ if (t & 0x04) /* King side */
+ {
+ rookf = t + 1;
+ rookt = t - 1;
+ }
+ else /* Queen side */
+ {
+ rookf = t - 2;
+ rookt = t + 1;
+ }
+ a = &board.b[side][rook];
+ CLEARBIT (*a, rookt);
+ SETBIT (*a, rookf);
+ CLEARBIT (board.blockerr90, r90[rookt]);
+ SETBIT (board.blockerr90, r90[rookf]);
+ CLEARBIT (board.blockerr45, r45[rookt]);
+ SETBIT (board.blockerr45, r45[rookf]);
+ CLEARBIT (board.blockerr315, r315[rookt]);
+ SETBIT (board.blockerr315, r315[rookf]);
+ cboard[rookf] = rook;
+ cboard[rookt] = empty;
+ Mvboard[rookf] = 0;
+ Mvboard[rookt] = 0;
+ board.castled[side] = false;
+ }
+
+ UpdateFriends ();
+ board.side = side;
+ board.ep = g->epsq;
+ board.flag = g->bflag;
+ HashKey = g->hashkey;
+ PawnHashKey = g->phashkey;
+ Game50 = g->Game50;
+ GameCnt--;
+ return;
+}
+
+
+void SANMove (int move, int ply)
+/****************************************************************************
+ *
+ * Convert the move to a SAN format. GenMoves (ply) needs to be called
+ * by the calling routine for this to work.
+ *
+ ****************************************************************************/
+{
+ int side;
+ int piece, ambiguous;
+ int f, t;
+ BitBoard b;
+ leaf *node1;
+ char *s;
+
+ side = board.side;
+ s = SANmv;
+ f = FROMSQ(move);
+ t = TOSQ(move);
+ /* Check some special moves like castling */
+ if (move & CASTLING)
+ {
+ if (t == 6 || t == 62)
+ strcpy (s, "O-O");
+ else
+ strcpy (s, "O-O-O");
+ return;
+ }
+
+/****************************************************************************
+ *
+ * Here split the code into 2 parts for clarity sake. First part deals
+ * with pawn moves only, 2nd part only piece moves. However before doing
+ * that, see if the move is ambiguous.
+ *
+ ****************************************************************************/
+
+ /* AMBIGUITY CHECK */
+ piece = cboard[f];
+ side = board.side;
+ b = board.b[side][piece];
+ ambiguous = false;
+ node1 = TreePtr[ply];
+ if (nbits (b) > 1)
+ {
+ /*
+ * Scan the movelist to see if another same-type piece is
+ * also moving to that particular to-square.
+ */
+ for (node1 = TreePtr[ply]; node1 < TreePtr[ply + 1]; node1++)
+ {
+ if (FROMSQ(node1->move) == f)
+ continue; /* original piece, skip */
+ if (TOSQ(node1->move) != t)
+ continue; /* diff to-square, skip */
+ if (cboard[FROMSQ(node1->move)] != piece)
+ continue; /* diff piece */
+ ambiguous = true;
+ break;
+ }
+ }
+
+ if (piece == pawn)
+ {
+ /* Capture or enpassant */
+ if (cboard[t] != 0 || board.ep == t)
+ {
+ *s++ = algbrfile [ROW (f)];
+ *s++ = 'x';
+ }
+ strcpy (s, algbr[t]);
+ s += 2;
+
+ /* Promotion */
+ if (move & PROMOTION)
+ {
+ *s++ = '=';
+ *s++ = notation[PROMOTEPIECE (move)];
+ }
+ }
+ else /* its not pawn */
+ {
+ *s++ = notation[piece];
+ if (ambiguous)
+ {
+ if (ROW (f) == ROW (FROMSQ(node1->move)))
+ *s++ = algbrrank[RANK (f)];
+ else
+ *s++ = algbrfile[ROW (f)];
+ }
+ if (cboard[t] != 0) /* capture */
+ *s++ = 'x';
+ strcpy (s, algbr[t]);
+ s += 2;
+ }
+
+ /* See if it is a checking or mating move */
+ MakeMove (side, &move);
+ if (SqAtakd (board.king[1^side], side))
+ {
+ TreePtr[ply+2] = TreePtr[ply+1];
+ GenCheckEscapes (ply+1);
+ if (TreePtr[ply+1] == TreePtr[ply+2])
+ *s++ = '#';
+ else
+ *s++ = '+';
+ GenCnt -= TreePtr[ply+2] - TreePtr[ply+1];
+ }
+ UnmakeMove (1^side, &move);
+
+ *s = '\0';
+ return;
+}
+
+
+#define ASCIITOFILE(a) ((a) - 'a')
+#define ASCIITORANK(a) ((a) - '1')
+#define ASCIITOSQ(a,b) (ASCIITOFILE(a)) + (ASCIITORANK(b)) * 8
+#define ATOH(a) ((a) >= 'a' && (a) <= 'h')
+#define ITO8(a) ((a) >= '1' && (a) <= '8')
+
+static inline int piece_id(const char c)
+{
+/* Given c, what is the piece id. This only takes one char, which
+ * isn't enough to handle two-character names (common in Russian text
+ * and old English notation that used Kt), but we're not supposed to
+ * see such text here anyway. This will
+ * accept "P" for pawn, and many lowercase chars (but not "b" for Bishop). */
+ switch (c)
+ {
+ case 'n':
+ case 'N':
+ return knight;
+ case 'B':
+ return bishop;
+ case 'r':
+ case 'R':
+ return rook;
+ case 'q':
+ case 'Q':
+ return queen;
+ case 'k':
+ case 'K':
+ return king;
+ case 'p':
+ case 'P':
+ return pawn;
+ }
+ return empty;
+}
+
+
+
+leaf * ValidateMove (char *s)
+/*************************************************************************
+ *
+ * This routine takes a string and check to see if it is a legal move.
+ * Note. At the moment, we accept 2 types of moves notation.
+ * 1. e2e4 format. 2. SAN format. (e4)
+ *
+ **************************************************************************/
+{
+ short f, t, side, rank, file, fileto;
+ short piece, piece2, kount;
+ char promote;
+ char mvstr[MAXSTR], *p;
+ BitBoard b, b2;
+ leaf *n1, *n2;
+
+ TreePtr[2] = TreePtr[1];
+ GenMoves (1);
+ FilterIllegalMoves (1);
+ side = board.side;
+
+ /************************************************************************
+ * The thing to do now is to clean up the move string. This
+ * gets rid of things like 'x', '+', '=' and so forth.
+ ************************************************************************/
+ p = mvstr;
+ do
+ {
+ if (*s != 'x' && *s != '+' && *s != '=' && !isspace(*s))
+ *p++ = *s;
+ } while (*s++ != '\0' );
+
+ /* Flush castles that check */
+ if (mvstr[strlen(mvstr)-1] == '+' || mvstr[strlen(mvstr)-1] == '#' ||
+ mvstr[strlen(mvstr)-1] == '=') mvstr[strlen(mvstr)-1] = '\000';
+
+ /* Check for castling */
+ if (strcmp (mvstr, "O-O") == 0 || strcmp (mvstr, "o-o") == 0 ||
+ strcmp (mvstr, "0-0") == 0)
+ {
+ if (side == white)
+ {
+ f = 4; t = 6;
+ }
+ else
+ {
+ f = 60; t = 62;
+ }
+ return (IsInMoveList (1, f, t, ' '));
+ }
+
+ if (strcmp (mvstr, "O-O-O") == 0 || strcmp (mvstr, "o-o-o") == 0 ||
+ strcmp (mvstr, "0-0-0") == 0)
+ {
+ if (side == white)
+ {
+ f = 4; t = 2;
+ }
+ else
+ {
+ f = 60; t = 58;
+ }
+ return (IsInMoveList (1, f, t, ' '));
+ }
+
+ /* Test to see if it is e2e4 type notation */
+ if (ATOH (mvstr[0]) && ITO8 (mvstr[1]) && ATOH (mvstr[2]) &&
+ ITO8 (mvstr[3]))
+ {
+ f = ASCIITOSQ (mvstr[0], mvstr[1]);
+ t = ASCIITOSQ (mvstr[2], mvstr[3]);
+ piece = (strlen (mvstr) == 5 ? mvstr[4] : ' ');
+ return (IsInMoveList (1, f, t, piece));
+ }
+
+
+ /***********************************************************************
+ * Its a SAN notation move. More headache!
+ * We generate all the legal moves and start comparing them with
+ * the input move.
+ ***********************************************************************/
+ if (ATOH (mvstr[0])) /* pawn move */
+ {
+ if (ITO8 (mvstr[1])) /* e4 type */
+ {
+ t = ASCIITOSQ (mvstr[0], mvstr[1]);
+ f = t + (side == white ? -8 : 8);
+ /* Add Sanity Check */
+ if ( f > 0 && f < 64 ) {
+ if (BitPosArray[f] & board.b[side][pawn])
+ {
+ if (mvstr[2] != '\0')
+ return (IsInMoveList (1, f, t, mvstr[2]));
+ else
+ return (IsInMoveList (1, f, t, ' '));
+ }
+ f = t + (side == white ? -16 : 16);
+ if ( f > 0 && f < 64 ) {
+ if (BitPosArray[f] & board.b[side][pawn])
+ return (IsInMoveList (1, f, t, ' '));
+ } /* End bound check +/- 16 */
+ } /* End bound check +/- 8 */
+ }
+ else if (ATOH (mvstr[1]) && ITO8 (mvstr[2])) /* ed4 type */
+ {
+ t = ASCIITOSQ (mvstr[1], mvstr[2]);
+ rank = ASCIITORANK (mvstr[2]) + (side == white ? -1 : 1);
+ f = rank * 8 + ASCIITOFILE (mvstr[0]);
+ piece = (strlen (mvstr) == 4 ? mvstr[3] : ' ');
+ return (IsInMoveList (1, f, t, piece));
+ }
+ else if (ATOH (mvstr[1])) /* ed type */
+ {
+ file = ASCIITOFILE (mvstr[0]);
+ fileto = ASCIITOFILE (mvstr[1]);
+ b = board.b[side][pawn] & FileBit[file];
+ if (side == white)
+ b = b >> (fileto < file ? 7 : 9);
+ else
+ b = b << (fileto < file ? 9 : 7);
+ if (board.ep > -1)
+ b = b & (board.friends[1^side] | BitPosArray[board.ep]);
+ else
+ b = b & (board.friends[1^side]);
+ switch (nbits (b))
+ {
+ case 0 : return ((leaf *) NULL);
+ case 1 : t = leadz (b);
+ f = t - (side == white ? 8 : -8) + (file - fileto);
+ piece = (strlen (mvstr) == 3 ? mvstr[2] : ' ');
+ return (IsInMoveList (1, f, t, piece));
+ default :
+ printf ("Ambiguous move: %s %s\n",s,mvstr);
+ ShowBoard();
+/*
+ getchar();
+*/
+ return ((leaf *) NULL);
+ }
+ }
+
+ }
+ else if ((piece = piece_id(mvstr[0])) != empty &&
+ (piece_id(mvstr[1]) == empty)) /* Is a piece move */
+ {
+ /* Since piece_id accepts P as pawns, this will correctly
+ * handle malformed commands like Pe4 */
+
+ b = board.b[side][piece];
+ t = -1;
+ if (ITO8 (mvstr[1])) /* N1d2 type move */
+ {
+ rank = ASCIITORANK (mvstr[1]);
+ b &= RankBit[rank];
+ t = ASCIITOSQ (mvstr[2], mvstr[3]);
+ }
+ else if (ATOH (mvstr[1]) && ATOH (mvstr[2])) /* Nbd2 type move */
+ {
+ file = ASCIITOFILE (mvstr[1]);
+ b &= FileBit[file];
+ t = ASCIITOSQ (mvstr[2], mvstr[3]);
+ }
+ else if (ATOH (mvstr[1]) && ITO8 (mvstr[2])) /* Nd2 type move */
+ {
+ t = ASCIITOSQ (mvstr[1], mvstr[2]);
+ }
+
+ kount = 0;
+ n1 = n2 = (leaf *) NULL;
+ while (b)
+ {
+ f = leadz (b);
+ CLEARBIT (b, f);
+ if ((n1 = IsInMoveList (1, f, t, ' ')) != (leaf *) NULL )
+ {
+ n2 = n1;
+ kount++;
+ }
+ }
+ if (kount > 1)
+ {
+ printf ("Ambiguous move: %s %s\n",s,mvstr);
+ ShowBoard();
+/*
+ getchar();
+*/
+ return ((leaf *) NULL);
+ }
+ else if (kount == 0)
+ return ((leaf *) NULL);
+ else
+ return (n2);
+ }
+ else if (((piece = piece_id(mvstr[0])) != empty) &&
+ ((piece2 = piece_id(mvstr[1])) != empty) &&
+ ( (mvstr[2] == '\0') ||
+ ((piece_id(mvstr[2]) != empty) && mvstr[3] == '\0')))
+ { /* KxP format */
+ promote = ' ';
+ if (piece_id(mvstr[2] != empty)) {
+ promote = mvstr[2];
+ }
+ kount = 0;
+ n1 = n2 = (leaf *) NULL;
+ b = board.b[side][piece];
+ while (b)
+ {
+ f = leadz (b);
+ CLEARBIT (b, f);
+ b2 = board.b[1^side][piece2];
+ while (b2)
+ {
+ t = leadz (b2);
+ CLEARBIT (b2, t);
+ printf("Trying %s: ", AlgbrMove(MOVE(f,t)));
+ if ((n1 = IsInMoveList (1, f, t, promote)) != (leaf *) NULL)
+ {
+ n2 = n1;
+ kount++;
+ printf("Y ");
+ }
+ else printf("N ");
+ }
+ }
+ if (kount > 1)
+ {
+ printf ("Ambiguous move: %s %s\n",s,mvstr);
+ ShowBoard();
+/*
+ getchar();
+*/
+ return ((leaf *) NULL);
+ }
+ else if (kount == 0)
+ return ((leaf *) NULL);
+ else
+ return (n2);
+
+ }
+
+ /* Fall through. Nothing worked, return that no move was performed. */
+ return ((leaf *) NULL);
+}
+
+
+leaf * IsInMoveList (int ply, int f, int t, char piece)
+/**************************************************************************
+ *
+ * Checks to see if from and to square can be found in the movelist
+ * and is legal.
+ *
+ **************************************************************************/
+{
+ leaf *node;
+
+ for (node = TreePtr[ply]; node < TreePtr[ply + 1]; node++)
+ {
+ if ((int) (node->move & 0x0FFF) == MOVE(f,t) &&
+ toupper(piece) == notation[PROMOTEPIECE (node->move)])
+ return (node);
+ }
+ return ((leaf *) NULL);
+}
+
+
+int IsLegalMove (int move)
+/*****************************************************************************
+ *
+ * Check that a move is legal on the current board.
+ * Perform some preliminary sanity checks.
+ * 1. If from square is emtpy, illegal.
+ * 2. Piece not of right color.
+ * 3. To square is friendly, illegal.
+ * 4. Promotion move or enpassant, so piece must be pawn.
+ * 5. Castling move, piece must be king.
+ * Note that IsLegalMove() no longer care about if a move will place the
+ * king in check. This will be caught by the Search().
+ *
+ *****************************************************************************/
+{
+ int side;
+ int f, t, piece;
+ BitBoard blocker, enemy;
+
+ f = FROMSQ(move);
+ t = TOSQ(move);
+
+ /* Empty from square */
+ if (cboard[f] == empty)
+ return (false);
+
+ /* Piece is not right color */
+ side = board.side;
+ if (!(BitPosArray[f] & board.friends[side]))
+ return (false);
+
+ /* TO square is a friendly piece, so illegal move */
+ if (BitPosArray[t] & board.friends[side])
+ return (false);
+
+ piece = cboard[f];
+ /* If promotion move, piece must be pawn */
+ if ((move & (PROMOTION | ENPASSANT)) && piece != pawn)
+ return (false);
+
+ /* If enpassant, then the enpassant square must be correct */
+ if ((move & ENPASSANT) && t != board.ep)
+ return (false);
+
+ /* If castling, then make sure its the king */
+ if ((move & CASTLING) && piece != king)
+ return (false);
+
+ blocker = board.blocker;
+ /* Pawn moves need to be handle specially */
+ if (piece == pawn)
+ {
+ if ((move & ENPASSANT) && board.ep > -1)
+ enemy = board.friends[1^side] | BitPosArray[board.ep];
+ else
+ enemy = board.friends[1^side];
+ if (side == white)
+ {
+ if (!(MoveArray[pawn][f] & BitPosArray[t] & enemy) &&
+ !(t - f == 8 && cboard[t] == empty) &&
+ !(t - f == 16 && RANK(f) == 1 && !(FromToRay[f][t] & blocker)))
+ return (false);
+ }
+ else if (side == black)
+ {
+ if (!(MoveArray[bpawn][f] & BitPosArray[t] & enemy) &&
+ !(t - f == -8 && cboard[t] == empty) &&
+ !(t - f == -16 && RANK(f) == 6 && !(FromToRay[f][t] & blocker)))
+ return (false);
+ }
+ }
+ /* King moves are also special, especially castling */
+ else if (piece == king)
+ {
+ if (side == white)
+ {
+ if (!(MoveArray[piece][f] & BitPosArray[t]) &&
+ !(f == E1 && t == G1 && board.flag & WKINGCASTLE &&
+ !(FromToRay[E1][G1] & blocker) && !SqAtakd(E1,black) &&
+ !SqAtakd(F1,black)) &&
+ !(f == E1 && t == C1 && board.flag & WQUEENCASTLE &&
+ !(FromToRay[E1][B1] & blocker) && !SqAtakd(E1,black) &&
+ !SqAtakd(D1,black)))
+ return (false);
+ }
+ if (side == black)
+ {
+ if (!(MoveArray[piece][f] & BitPosArray[t]) &&
+ !(f == E8 && t == G8 && board.flag & BKINGCASTLE &&
+ !(FromToRay[E8][G8] & blocker) && !SqAtakd(E8,white) &&
+ !SqAtakd(F8,white)) &&
+ !(f == E8 && t == C8 && board.flag & BQUEENCASTLE &&
+ !(FromToRay[E8][B8] & blocker) && !SqAtakd(E8,white) &&
+ !SqAtakd(D8,white)))
+ return (false);
+ }
+ }
+ else
+ {
+ if (!(MoveArray[piece][f] & BitPosArray[t]))
+ return (false);
+ }
+
+ /* If there is a blocker on the path from f to t, illegal move */
+ if (slider[piece])
+ {
+ if (FromToRay[f][t] & NotBitPosArray[t] & blocker)
+ return (false);
+ }
+
+ return (true);
+}
+
+char *AlgbrMove (int move)
+/*****************************************************************************
+ *
+ * Convert an int move format to algebraic format of g1f3.
+ *
+ *****************************************************************************/
+{
+ int f, t;
+ static char s[6];
+
+ f = FROMSQ(move);
+ t = TOSQ(move);
+ strcpy (s, algbr[f]);
+ strcpy (s+2, algbr[t]);
+ if (move & PROMOTION)
+ {
+ if (flags & XBOARD)
+ s[4] = lnotation[PROMOTEPIECE (move)];
+ else
+ s[4] = notation[PROMOTEPIECE (move)];
+ s[5] = '\0';
+ }
+ else
+ s[4] = '\0';
+ return (s);
+}
+
diff --git a/src/chess_computer-activity/gnuchess/null.c b/src/chess_computer-activity/gnuchess/null.c
new file mode 100644
index 0000000..a2c48b4
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/null.c
@@ -0,0 +1,77 @@
+/* GNU Chess 5.0 - null.c - null move code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+void MakeNullMove (int side)
+/*****************************************************************************
+ *
+ * Makes a null move on the board and update the various game information.
+ *
+ *****************************************************************************/
+{
+ GameRec *g;
+
+ GameCnt++;
+ g = &Game[GameCnt];
+ g->epsq = board.ep;
+ g->bflag = board.flag;
+ g->hashkey = HashKey;
+ if (board.ep > -1)
+ HashKey ^= ephash[board.ep];
+ HashKey ^= Sidehash;
+ board.ep = -1;
+ board.side = 1^side;
+
+ /* Update game record */
+ g->move = NULLMOVE;
+ return;
+}
+
+
+void UnmakeNullMove (int side)
+/****************************************************************************
+ *
+ * Undoing a null move.
+ *
+ ****************************************************************************/
+{
+ GameRec *g;
+
+ side = 1^side;
+ board.side = side;
+ g = &Game[GameCnt];
+ board.ep = g->epsq;
+ board.flag = g->bflag;
+ HashKey = g->hashkey;
+ GameCnt--;
+ return;
+}
diff --git a/src/chess_computer-activity/gnuchess/output.c b/src/chess_computer-activity/gnuchess/output.c
new file mode 100644
index 0000000..23011c5
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/output.c
@@ -0,0 +1,303 @@
+/* GNU Chess 5.0 - output.c - output code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+void ShowTime (void)
+/**************************************************************************
+ *
+ * Print out the time settings.
+ *
+ **************************************************************************/
+{
+}
+
+void ShowMoveList (int ply)
+/**************************************************************************
+ *
+ * Print out the move list.
+ *
+ **************************************************************************/
+{
+ leaf *node;
+ int i = 0;
+
+ for (node = TreePtr[ply]; node < TreePtr[ply+1]; node++)
+ {
+ SANMove (node->move, ply);
+ printf ("%5s %3d\t", SANmv, SwapOff(node->move));
+ if (++i == 5)
+ {
+ printf ("\n");
+ i = 0;
+ }
+ }
+ printf ("\n");
+}
+
+
+void ShowSmallBoard (void)
+/*****************************************************************************
+ *
+ * Display the board. Not only that but display some useful information
+ * like whether enpassant is legal and castling state.
+ *
+ *****************************************************************************/
+{
+ int r, c, sq;
+
+ printf ("\n");
+ if (board.side == white)
+ printf ("white ");
+ else
+ printf ("black ");
+
+ if (board.flag & WKINGCASTLE)
+ printf ("K");
+ if (board.flag & WQUEENCASTLE)
+ printf ("Q");
+ if (board.flag & BKINGCASTLE)
+ printf ("k");
+ if (board.flag & BQUEENCASTLE)
+ printf ("q");
+
+ if (board.ep > -1)
+ printf (" %s", algbr[board.ep]);
+
+ printf ("\n");
+ for (r = 56; r >= 0; r -= 8)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ sq = r + c;
+ if (board.b[white][pawn] & BitPosArray[sq])
+ printf ("P ");
+ else if (board.b[white][knight] & BitPosArray[sq])
+ printf ("N ");
+ else if (board.b[white][bishop] & BitPosArray[sq])
+ printf ("B ");
+ else if (board.b[white][rook] & BitPosArray[sq])
+ printf ("R ");
+ else if (board.b[white][queen] & BitPosArray[sq])
+ printf ("Q ");
+ else if (board.b[white][king] & BitPosArray[sq])
+ printf ("K ");
+ else if (board.b[black][pawn] & BitPosArray[sq])
+ printf ("p ");
+ else if (board.b[black][knight] & BitPosArray[sq])
+ printf ("n ");
+ else if (board.b[black][bishop] & BitPosArray[sq])
+ printf ("b ");
+ else if (board.b[black][rook] & BitPosArray[sq])
+ printf ("r ");
+ else if (board.b[black][queen] & BitPosArray[sq])
+ printf ("q ");
+ else if (board.b[black][king] & BitPosArray[sq])
+ printf ("k ");
+ else
+ printf (". ");
+ }
+ printf ("\n");
+ }
+ printf ("\n");
+}
+
+
+
+void ShowBitBoard (BitBoard *b)
+/*****************************************************************************
+ *
+ * Just to print a lousy ascii board
+ *
+ *****************************************************************************/
+{
+ int r, c;
+
+ printf ("\n");
+ for (r = 56; r >= 0; r -= 8)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ if (*b & BitPosArray[r + c])
+ printf ("1 ");
+ else
+ printf (". ");
+ }
+ printf ("\n");
+ }
+ printf ("\n");
+}
+
+
+void ShowBoard (void)
+/*****************************************************************************
+ *
+ * Display the board. Not only that but display some useful information
+ * like whether enpassant is legal and castling state.
+ *
+ *****************************************************************************/
+{
+ int r, c, sq;
+
+ fprintf (ofp, "\n");
+ if (board.side == white)
+ fprintf (ofp, "white ");
+ else
+ fprintf (ofp, "black ");
+
+ if (board.flag & WKINGCASTLE)
+ fprintf (ofp, "K");
+ if (board.flag & WQUEENCASTLE)
+ fprintf (ofp, "Q");
+ if (board.flag & BKINGCASTLE)
+ fprintf (ofp, "k");
+ if (board.flag & BQUEENCASTLE)
+ fprintf (ofp, "q");
+
+ if (board.ep > -1)
+ fprintf (ofp, " %s", algbr[board.ep]);
+
+ fprintf (ofp, "\n");
+ for (r = 56; r >= 0; r -= 8)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ sq = r + c;
+ if (board.b[white][pawn] & BitPosArray[sq])
+ fprintf (ofp, "P ");
+ else if (board.b[white][knight] & BitPosArray[sq])
+ fprintf (ofp, "N ");
+ else if (board.b[white][bishop] & BitPosArray[sq])
+ fprintf (ofp, "B ");
+ else if (board.b[white][rook] & BitPosArray[sq])
+ fprintf (ofp, "R ");
+ else if (board.b[white][queen] & BitPosArray[sq])
+ fprintf (ofp, "Q ");
+ else if (board.b[white][king] & BitPosArray[sq])
+ fprintf (ofp, "K ");
+ else if (board.b[black][pawn] & BitPosArray[sq])
+ fprintf (ofp, "p ");
+ else if (board.b[black][knight] & BitPosArray[sq])
+ fprintf (ofp, "n ");
+ else if (board.b[black][bishop] & BitPosArray[sq])
+ fprintf (ofp, "b ");
+ else if (board.b[black][rook] & BitPosArray[sq])
+ fprintf (ofp, "r ");
+ else if (board.b[black][queen] & BitPosArray[sq])
+ fprintf (ofp, "q ");
+ else if (board.b[black][king] & BitPosArray[sq])
+ fprintf (ofp, "k ");
+ else
+ fprintf (ofp, ". ");
+ }
+ fprintf (ofp, "\n");
+ }
+ fprintf (ofp, "\n");
+}
+
+void ShowCBoard (void)
+/*****************************************************************************
+ *
+ *
+ *
+ *****************************************************************************/
+{
+ int r, c;
+
+ for (r = 56; r >= 0; r -= 8)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ printf ("%2c ", cboard[r + c] ? notation[cboard[r+c]] : '.');
+ }
+ printf ("\n");
+ }
+ printf ("\n");
+}
+
+
+void ShowMvboard (void)
+/*****************************************************************************
+ *
+ * Print the Mvboard[] array.
+ *
+ *****************************************************************************/
+{
+ int r, c;
+
+ for (r = 56; r >= 0; r -= 8)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ printf ("%2d ", Mvboard[r + c]);
+ }
+ printf ("\n");
+ }
+ printf ("\n");
+}
+
+void ShowGame (void)
+{
+ int i;
+
+/* *********************************************
+ * We must handle the special case of an EPD *
+ * game where the first move is by black *
+ ********************************************* */
+
+ if ( GameCnt >= 0 )
+ {
+
+ printf (" White Black\n");
+
+ if ( ( board.side == white && GameCnt % 2 == 1 ) ||
+ ( board.side == black && GameCnt % 2 == 0 ))
+ {
+
+ for (i = 0; i <= GameCnt; i += 2)
+ {
+ printf ("%3d. %-7s %-7s\n", i/2 + 1, Game[i].SANmv,
+ Game[i + 1].SANmv);
+ }
+ }
+ else {
+
+ printf (" 1. %-7s\n", Game[0].SANmv);
+
+ for (i = 1; i <= GameCnt; i += 2)
+ {
+ printf ("%3d. %-7s %-7s\n", i/2 + 2, Game[i].SANmv,
+ Game[i + 1].SANmv);
+ }
+ }
+ printf ("\n");
+ }
+}
diff --git a/src/chess_computer-activity/gnuchess/pgn.c b/src/chess_computer-activity/gnuchess/pgn.c
new file mode 100644
index 0000000..f731946
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/pgn.c
@@ -0,0 +1,390 @@
+/* GNU Chess 5.0 - pgn.c - pgn game format code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+
+#include "common.h"
+#include "version.h"
+#include "book.h"
+#include "lexpgn.h"
+
+#define NULL2EMPTY(x) ( (x) ? (x) : "")
+
+extern FILE *yyin;
+
+int yylex(void);
+
+void PGNSaveToFile (const char *file, const char *resultstr)
+/****************************************************************************
+ *
+ * To save a game into PGN format to a file. If the file does not exist,
+ * it will create it. If the file exists, the game is appended to the file.
+ *
+ ****************************************************************************/
+{
+ FILE *fp;
+ char s[100];
+ int len;
+ char *p;
+ int i;
+ time_t secs;
+ struct tm *timestruct;
+
+ fp = fopen (file, "a"); /* Can we append to it? */
+ if (fp == NULL)
+ {
+ printf ("Cannot write to file %s\n", file);
+ return;
+ }
+
+ /* Write the seven tags */
+ fprintf (fp, "[Event \"%s\"]\n", NULL2EMPTY(pgn_event));
+ fprintf (fp, "[Site \"%s\"]\n", NULL2EMPTY(pgn_site));
+ secs=time(0);
+ if (pgn_date)
+ fprintf(fp,"[Date \"%s\"]\n", pgn_date);
+ else {
+ timestruct=localtime((time_t*) &secs);
+ fprintf(fp,"[Date \"%4d.%02d.%02d\"]\n",timestruct->tm_year+1900,
+ timestruct->tm_mon+1,timestruct->tm_mday);
+ }
+ fprintf (fp, "[Round \"%s\"]\n", NULL2EMPTY(pgn_round));
+
+ if (pgn_white)
+ fprintf (fp, "[White \"%s\"]\n", pgn_white);
+ else if (computer == white)
+ fprintf (fp, "[White \"%s %s\"]\n",PROGRAM,VERSION);
+ else
+ fprintf (fp, "[White \"%s\"]\n",name);
+
+ if (pgn_black)
+ fprintf (fp, "[Black \"%s\"]\n", pgn_black);
+ else if (computer == black)
+ fprintf (fp, "[Black \"%s %s\"]\n",PROGRAM,VERSION);
+ else
+ fprintf (fp, "[Black \"%s\"]\n",name);
+
+ if (pgn_whiteELO)
+ fprintf (fp, "[WhiteELO \"%s\"]\n", NULL2EMPTY(pgn_white));
+ else
+ fprintf(fp, "[WhiteELO \"%d\"]\n",computer==white?myrating:opprating);
+ if (pgn_blackELO)
+ fprintf (fp, "[BlackELO \"%s\"]\n", NULL2EMPTY(pgn_black));
+ else
+ fprintf (fp, "[BlackELO \"%d\"]\n",computer==white?opprating:myrating);
+
+ if (pgn_result)
+ fprintf (fp, "[Result \"%s\"]\n", pgn_result);
+ else {
+ /* Revive the little-known standard functions! */
+ len = strcspn(resultstr," {");
+ fprintf (fp, "[Result \"%.*s\"]\n", len, resultstr);
+ }
+
+ if (pgn_othertags) {
+ fprintf (fp, "%s", pgn_othertags);
+ }
+
+ fprintf (fp, "\n");
+
+ if (initial_comments)
+ {
+ fprintf(fp, "\n%s\n", initial_comments);
+ /* If it doesn't end in \n, add it */
+ if (initial_comments[0] &&
+ initial_comments[strlen(initial_comments)-1] != '\n')
+ fprintf(fp, "\n");
+ }
+
+ s[0] = '\0';
+ for (i = 0; i <= GameCnt; i++)
+ {
+ if (! (i % 2)) {
+ sprintf (s, "%s%d. ", s, i/2 + 1);
+ }
+ sprintf (s, "%s%s ", s, Game[i].SANmv);
+ if (strlen (s) > 80)
+ {
+ p = s + 79;
+ while (*p-- != ' ');
+ *++p = '\0';
+ fprintf (fp, "%s\n", s);
+ strcpy (s, p+1);
+ }
+ if (Game[i].comments) {
+ fprintf (fp, "%s\n", s);
+ fprintf (fp, "%s", Game[i].comments);
+ if (Game[i].comments[0] &&
+ Game[i].comments[strlen(Game[i].comments)-1] != '\n')
+ fprintf(fp, "\n");
+ s[0] = '\0';
+ }
+ }
+ fprintf (fp, "%s", s);
+ fprintf (fp, "%s", resultstr);
+ fprintf (fp, "\n\n");
+ fclose (fp);
+
+}
+
+
+void PGNReadFromFile (const char *file)
+/****************************************************************************
+ *
+ * To read a game from a PGN file.
+ *
+ ****************************************************************************/
+{
+ FILE *fp;
+
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ {
+ printf ("Cannot open file %s\n", file);
+ return;
+ }
+ yyin = fp;
+
+ InitVars ();
+
+ data_dest = DEST_GAME;
+ (void) yylex();
+
+ fclose (fp);
+ ShowBoard ();
+ TTClear ();
+}
+
+/* Only players in the table below are permitted into the opening book
+ from the PGN files. Please expand the table as needed. Generally,
+ I would recommend only acknowledged GM's and IM's and oneself, but
+ because of the self-changing nature of the book, anything inferior
+ will eventually be eliminated through automatic play as long as
+ you feed the games the program plays back to itself with "book add pgnfile"
+*/
+/* TODO: Fix this so the list isn't hardcoded. */
+
+static const char *const trusted_players[] = {
+ "Alekhine",
+ "Adams",
+ "Anand",
+ "Anderssen",
+ "Andersson",
+ "Aronin",
+ "Averbakh",
+ "Balashov",
+ "Beliavsky",
+ "Benko",
+ "Bernstein",
+ "Bird",
+ "Bogoljubow",
+ "Bolbochan",
+ "Boleslavsky",
+ "Byrne",
+ "Botvinnik",
+ "Bronstein",
+ "Browne",
+ "Capablanca",
+ "Chigorin",
+ "Christiansen",
+ "De Firmian",
+ "Deep Blue",
+ "Deep Thought",
+ "Donner",
+ "Dreev",
+ "Duras",
+ "Euwe",
+ "Evans",
+ "Filip",
+ "Fine",
+ "Fischer",
+ "Flohr",
+ "Furman",
+ "Gelfand",
+ "Geller",
+ "Gereben",
+ "Glek",
+ "Gligoric",
+ "GNU",
+ "Golombek",
+ "Gruenfeld",
+ "Guimard",
+ "Hodgson",
+ "Ivanchuk",
+ "Ivkov",
+ "Janowsky",
+ "Kamsky",
+ "Kan",
+ "Karpov",
+ "Kasparov",
+ "Keres",
+ "Korchnoi",
+ "Kortschnoj",
+ "Kotov",
+ "Kramnik",
+ "Kupreich",
+ "Lasker",
+ "Lautier",
+ "Letelier",
+ "Lilienthal",
+ "Ljubojevic",
+ "Marshall",
+ "Maroczy",
+ "Mieses",
+ "Miles",
+ "Morphy",
+ "Mueller", /* Every other German has this name... */
+ "Nimzowitsch",
+ "Nunn",
+ "Opocensky",
+ "Pachman",
+ "Petrosian",
+ "Piket",
+ "Pilnik",
+ "Pirc",
+ "Polgar",
+ "Portisch",
+ "Psakhis",
+ "Ragozin",
+ "Reshevsky",
+ "Reti",
+ "Romanish",
+ "Rubinstein",
+ "Saemisch",
+ "Seirawan",
+ "Shirov",
+ "Short",
+ "Silman",
+ "Smyslov",
+ "Sokolsky",
+ "Spassky",
+ "Sveshnikov",
+ "Stahlberg",
+ "Steinitz",
+ "Tal",
+ "Tarjan",
+ "Tartakower",
+ "Timman",
+ "Topalov",
+ "Torre",
+ "Vidmar"
+
+ };
+
+int IsTrustedPlayer(const char *name)
+/* Return 1 if name in trusted_players list, else 0 */
+{
+ int i;
+ for (i = 0; i < (sizeof(trusted_players) / sizeof(*trusted_players));
+ i++) {
+ if (strstr(name, trusted_players[i]) != NULL)
+ return 1;
+ }
+ return 0;
+}
+
+void BookPGNReadFromFile (const char *file)
+/****************************************************************************
+ *
+ * To read a game from a PGN file and store out the hash entries to book.
+ *
+ ****************************************************************************/
+{
+ FILE *fp;
+ int ngames = 0;
+ time_t t1, t2;
+ double et;
+ int error;
+
+ /* TODO: Fix reading from file */
+
+ et = 0.0;
+ t1 = time(NULL);
+
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "Cannot open file %s: %s\n",
+ file, strerror(errno));
+ return;
+ }
+ yyin = fp;
+
+ /* Maybe add some more clever error handling later */
+ if (BookBuilderOpen() != BOOK_SUCCESS)
+ return;
+ newpos = existpos = 0;
+ data_dest = DEST_BOOK;
+
+ while(1) {
+ InitVars ();
+ NewPosition ();
+ CLEAR (flags, MANUAL);
+ CLEAR (flags, THINK);
+ myrating = opprating = 0;
+
+ error = yylex();
+ if (error) break;
+
+ ngames++;
+ if (ngames % 10 == 0) printf("Games processed: %d\r",ngames);
+ fflush(stdout);
+ }
+
+ fclose (fp);
+ if (BookBuilderClose() != BOOK_SUCCESS) {
+ perror("Error writing opening book during BookBuilderClose");
+ }
+
+ /* Reset the board otherwise we leave the last position in the book
+ on the board. */
+ InitVars ();
+ NewPosition ();
+ CLEAR (flags, MANUAL);
+ CLEAR (flags, THINK);
+ myrating = opprating = 0;
+
+ t2 = time(NULL);
+ et += difftime(t2, t1);
+ putchar('\n');
+
+ /* Handle divide-by-zero problem */
+ if (et < 0.5) { et = 1.0; };
+
+ printf("Time = %.0f seconds\n", et);
+ printf("Games compiled: %d\n",ngames);
+ printf("Games per second: %f\n",ngames/et);
+ printf("Positions scanned: %d\n",newpos+existpos);
+ printf("Positions per second: %f\n",(newpos+existpos)/et);
+ printf("New & unique added: %d positions\n",newpos);
+ printf("Duplicates not added: %d positions\n",existpos);
+}
diff --git a/src/chess_computer-activity/gnuchess/players.c b/src/chess_computer-activity/gnuchess/players.c
new file mode 100644
index 0000000..7d0b8ac
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/players.c
@@ -0,0 +1,212 @@
+
+/* GNU Chess 5.0 - player.c - database on players
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "common.h"
+#include "book.h"
+
+#define PLAYERFILE "players.dat"
+
+int totalplayers = 0;
+
+#define MAXPLAYERS 500
+
+typedef struct {
+ char player[MAXNAMESZ];
+ int wins;
+ int losses;
+ int draws;
+} playerentry;
+
+playerentry playerdb[MAXPLAYERS];
+static char lname[MAXNAMESZ];
+
+static int rscorecompare(const void *aa, const void *bb)
+{
+ const playerentry *a = aa;
+ const playerentry *b = bb;
+ float ascore, bscore;
+ ascore = (a->wins+(a->draws/2))/(a->wins+a->draws+a->losses);
+ bscore = (b->wins+(b->draws/2))/(b->wins+b->draws+b->losses);
+ if (ascore > bscore) return(-1);
+ else if (bscore > ascore) return(1);
+ else return(0);
+}
+
+static int scorecompare(const void *aa, const void *bb)
+{
+ const playerentry *a = aa;
+ const playerentry *b = bb;
+ int ascore, bscore;
+ ascore = 100*(a->wins+(a->draws/2))/(a->wins+a->draws+a->losses);
+ bscore = 100*(b->wins+(b->draws/2))/(b->wins+b->draws+b->losses);
+ if (bscore > ascore) return(1);
+ else if (bscore < ascore) return(-1);
+ else return(0);
+}
+
+static int namecompare(const void *aa, const void *bb)
+{
+ const playerentry *a = aa;
+ const playerentry *b = bb;
+ if (strcmp(a->player,b->player) > 0) return(1);
+ else if (strcmp(a->player,b->player) < 0) return(-1);
+ else return(0);
+}
+
+void DBSortPlayer (const char *style)
+{
+ if (strncmp(style,"score",5) == 0) {
+ qsort(&playerdb,totalplayers,sizeof(playerentry),scorecompare);
+ } else if (strncmp(style,"name",4) == 0) {
+ qsort(&playerdb,totalplayers,sizeof(playerentry),namecompare);
+ } else if (strncmp(style,"reverse",7) == 0) {
+ qsort(&playerdb,totalplayers,sizeof(playerentry),rscorecompare);
+ }
+}
+
+void DBListPlayer (const char *style)
+{
+ int i;
+
+ DBReadPlayer ();
+ DBSortPlayer (style);
+ for (i = 0; i < totalplayers; i++) {
+ printf("%s %2.0f%% %d %d %d\n",
+ playerdb[i].player,
+ 100.0*(playerdb[i].wins+((float)playerdb[i].draws/2))/
+ (playerdb[i].wins+playerdb[i].draws+playerdb[i].losses),
+ playerdb[i].wins,
+ playerdb[i].losses,
+ playerdb[i].draws);
+ if ((i+1) % 10 == 0) {printf("[Type a character to continue.]\n"); getchar();}
+ }
+}
+
+void DBWritePlayer (void)
+{
+ int i;
+ float result1;
+ int result2;
+ FILE *wfp;
+ DBSortPlayer ("reverse");
+ if ((wfp = fopen(PLAYERFILE,"w")) != NULL) {
+ for (i = 0; i < totalplayers; i++) {
+ result1 =
+ 100.0*(playerdb[i].wins+((float)playerdb[i].draws/2))/
+ (playerdb[i].wins+playerdb[i].draws+playerdb[i].losses),
+ result2 = (int) result1;
+ fprintf(wfp,"%s %d %d %d\n",
+ playerdb[i].player,
+ playerdb[i].wins,
+ playerdb[i].losses,
+ playerdb[i].draws);
+ }
+ }
+ fclose(wfp);
+}
+
+void DBReadPlayer (void)
+{
+ FILE *rfp;
+ int n;
+ totalplayers = 0;
+ if ((rfp = fopen(PLAYERFILE,"r")) != NULL) {
+ while (!feof(rfp)) {
+ n = fscanf(rfp,"%49s %d %d %d\n", /* 49 MAXNAMESZ-1 */
+ playerdb[totalplayers].player,
+ &playerdb[totalplayers].wins,
+ &playerdb[totalplayers].losses,
+ &playerdb[totalplayers].draws);
+ if (n == 4) totalplayers++;
+ }
+ fclose(rfp);
+ }
+}
+
+int DBSearchPlayer (const char *player)
+{
+ int index = -1;
+ int i;
+
+ for (i = 0; i < totalplayers; i++)
+ if (strncmp(playerdb[i].player,player,strlen(playerdb[i].player)) == 0)
+ {
+ index = i;
+ break;
+ }
+ return (index);
+}
+
+void DBUpdatePlayer (const char *player, const char *resultstr)
+{
+ const char *p;
+ char *x;
+ int index;
+ int result = R_NORESULT;
+
+ p = player;
+ x = lname;
+ strcpy(lname,player);
+ do {
+ if (*p != ' ')
+ *x++ = *p++;
+ else
+ p++;
+ } while (*p != '\0');
+ *x = '\000';
+ memset(playerdb,0,sizeof(playerdb));
+ DBReadPlayer ();
+ index = DBSearchPlayer (lname);
+ if (index == -1) {
+ strcpy(playerdb[totalplayers].player,lname);
+ playerdb[totalplayers].wins = 0;
+ playerdb[totalplayers].losses = 0;
+ playerdb[totalplayers].draws = 0;
+ index = totalplayers;
+ totalplayers++;
+ }
+ if (strncmp(resultstr,"1-0",3) == 0)
+ result = R_WHITE_WINS;
+ else if (strncmp(resultstr,"0-1",3) == 0)
+ result = R_BLACK_WINS;
+ else if (strncmp(resultstr,"1/2-1/2",7) == 0)
+ result = R_DRAW;
+
+ if ((computerplays == white && result == R_WHITE_WINS)||
+ (computerplays == black && result == R_BLACK_WINS))
+ playerdb[index].wins++;
+ else if ((computerplays == white && result == R_BLACK_WINS)||
+ (computerplays == black && result == R_WHITE_WINS))
+ playerdb[index].losses++;
+ else
+ /* Shouln't one check for draw here? Broken PGN files surely exist */
+ playerdb[index].draws++;
+ DBWritePlayer ();
+}
diff --git a/src/chess_computer-activity/gnuchess/ponder.c b/src/chess_computer-activity/gnuchess/ponder.c
new file mode 100644
index 0000000..62bca6c
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/ponder.c
@@ -0,0 +1,58 @@
+/* GNU Chess 5.0 - ponder.c - Pondering
+ Copyright (c) 2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+ lukas debian org
+*/
+
+#include <config.h>
+#include "common.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * Pondering has to check for input_status == INPUT_NONE regularly,
+ * that is what Iterate() is supposed to do when the PONDER flag is
+ * set. Output should only be generated if the xboard flag is
+ * set. (Otherwise stdout gets messed up.)
+ */
+void ponder(void)
+{
+ /* Save flags and clear the time control bit for pondering */
+ const unsigned int saved_flags = flags;
+
+ /* Save number of moves out of book */
+ const int nmfb = nmovesfrombook;
+
+ CLEAR(flags, TIMECTL);
+ SET(flags, PONDER);
+
+ dbg_printf("Pondering, GameCnt = %d\n", GameCnt);
+ Iterate();
+ dbg_printf("Pondering ended, GameCnt = %d\n", GameCnt);
+
+ /* Restore flags, will also clear the PONDER flag */
+ flags=saved_flags;
+
+ nmovesfrombook = nmfb;
+}
diff --git a/src/chess_computer-activity/gnuchess/quiesce.c b/src/chess_computer-activity/gnuchess/quiesce.c
new file mode 100644
index 0000000..0980b98
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/quiesce.c
@@ -0,0 +1,114 @@
+/* GNU Chess 5.0 - quiesce.c - quiescence search code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+int Quiesce (uint8_t ply, int alpha, int beta)
+/**************************************************************************
+ *
+ * Our quiescent search. This quiescent search is able to recognize
+ * mates.
+ *
+ **************************************************************************/
+{
+ uint8_t side, xside;
+ int best, delta, score, savealpha;
+ leaf *p, *pbest;
+
+ if (EvaluateDraw ())
+ return (DRAWSCORE);
+
+ side = board.side;
+ xside = 1^side;
+ InChk[ply] = SqAtakd (board.king[side], xside);
+ best = Evaluate (alpha, beta);
+ if (best >= beta && !InChk[ply])
+ return (best);
+ TreePtr[ply+1] = TreePtr[ply];
+ if (InChk[ply])
+ {
+ GenCheckEscapes (ply);
+ if (TreePtr[ply] == TreePtr[ply+1])
+ return (-MATE+ply-2);
+ if (best >= beta)
+ return (best);
+ SortMoves (ply);
+ }
+ else
+ {
+ GenCaptures (ply);
+ if (TreePtr[ply] == TreePtr[ply+1])
+ return (best);
+ SortCaptures (ply);
+ }
+
+ savealpha = alpha;
+ pbest = NULL;
+ alpha = MAX(best, alpha);
+ delta = MAX (alpha - 150 - best, 0);
+
+ for (p = TreePtr[ply]; p < TreePtr[ply+1]; p++)
+ {
+ pick (p, ply);
+
+ /* We are in check or capture cannot bring score near alpha, give up */
+ if (!InChk[ply] && SwapOff (p->move) < delta)
+ continue;
+
+ /* If capture cannot bring score near alpha, give up */
+ if (p->score == -INFINITY)
+ continue;
+
+ MakeMove (side, &p->move);
+ QuiesCnt++;
+ if (SqAtakd (board.king[side], xside))
+ {
+ UnmakeMove (xside, &p->move);
+ continue;
+ }
+ score = -Quiesce (ply+1, -beta, -alpha);
+ UnmakeMove (xside, &p->move);
+ if (score > best)
+ {
+ best = score;
+ pbest = p;
+ if (best >= beta)
+ goto done;
+ alpha = MAX (alpha, best);
+ }
+ }
+
+done:
+ if (flags & USEHASH && pbest != NULL)
+ TTPut (side, 0, ply, savealpha, beta, best, pbest->move);
+
+ return (best);
+}
diff --git a/src/chess_computer-activity/gnuchess/random.c b/src/chess_computer-activity/gnuchess/random.c
new file mode 100644
index 0000000..e1243b8
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/random.c
@@ -0,0 +1,135 @@
+/* GNU Chess 5.0 - random.c - random number code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+uint32_t Rand32 (void)
+/****************************************************************************
+ *
+ * A 32 bit random number generator. An implementation in C of the
+ * algorithm given by Knuth, the art of computer programming, vol. 2,
+ * pp. 26-27. We use e=32, so we have to evaluate y(n) = y(n-24) + y(n-55)
+ * mod 2^32, which is implicitly done by unsigned arithmetic.
+ *
+ ****************************************************************************/
+{
+/*
+ * Random numbers from Mathematica 2.0
+ * SeedRandom = 1;
+ * Table[Random[Integer, {0, 2^32 - 1}]
+ */
+ static uint32_t x[55] =
+ {
+ 1410651636UL,
+ 3012776752UL,
+ 3497475623UL,
+ 2892145026UL,
+ 1571949714UL,
+ 3253082284UL,
+ 3489895018UL,
+ 387949491UL,
+ 2597396737UL,
+ 1981903553UL,
+ 3160251843UL,
+ 129444464UL,
+ 1851443344UL,
+ 4156445905UL,
+ 224604922UL,
+ 1455067070UL,
+ 3953493484UL,
+ 1460937157UL,
+ 2528362617UL,
+ 317430674UL,
+ 3229354360UL,
+ 117491133UL,
+ 832845075UL,
+ 1961600170UL,
+ 1321557429UL,
+ 747750121UL,
+ 545747446UL,
+ 810476036UL,
+ 503334515UL,
+ 4088144633UL,
+ 2824216555UL,
+ 3738252341UL,
+ 3493754131UL,
+ 3672533954UL,
+ 29494241UL,
+ 1180928407UL,
+ 4213624418UL,
+ 33062851UL,
+ 3221315737UL,
+ 1145213552UL,
+ 2957984897UL,
+ 4078668503UL,
+ 2262661702UL,
+ 65478801UL,
+ 2527208841UL,
+ 1960622036UL,
+ 315685891UL,
+ 1196037864UL,
+ 804614524UL,
+ 1421733266UL,
+ 2017105031UL,
+ 3882325900UL,
+ 810735053UL,
+ 384606609UL,
+ 2393861397UL
+ };
+ static int init = true;
+ static uint32_t y[55];
+ static int j, k;
+ uint32_t ul;
+
+ if (init)
+ {
+ int i;
+ init = false;
+ for (i = 0; i < 55; i++)
+ y[i] = x[i];
+ j = 24 - 1;
+ k = 55 - 1;
+ }
+ ul = (y[k] += y[j]);
+ if (--j < 0) j = 55 - 1;
+ if (--k < 0) k = 55 - 1;
+ return (ul);
+}
+
+HashType Rand64 (void)
+{
+ HashType b;
+
+ b = Rand32();
+ b = b << 32;
+ b |= Rand32 ();
+ return (b);
+}
diff --git a/src/chess_computer-activity/gnuchess/repeat.c b/src/chess_computer-activity/gnuchess/repeat.c
new file mode 100644
index 0000000..f74b74e
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/repeat.c
@@ -0,0 +1,45 @@
+/* GNU Chess 5.0 - repeat.c - repeat position detector code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include "common.h"
+
+short Repeat (void)
+{
+ int i, k;
+
+ k = 0;
+ for (i = GameCnt-3; i >= Game50; i-=2)
+ {
+ if (Game[i].hashkey == HashKey)
+ k++;
+ }
+ return (k);
+}
diff --git a/src/chess_computer-activity/gnuchess/search.c b/src/chess_computer-activity/gnuchess/search.c
new file mode 100644
index 0000000..c26dc3a
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/search.c
@@ -0,0 +1,734 @@
+/* GNU Chess 5.0 - search.c - tree-search code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "common.h"
+
+#define TIMECHECK 1023
+#define HISTSCORE(d) ((d)*(d))
+
+#define FUTSCORE (MATERIAL+fdel)
+#define GETNEXTMOVE (InChk[ply] ? PhasePick1 (&p, ply) : PhasePick (&p, ply))
+
+static inline void ShowThinking (leaf *p, uint8_t ply)
+{
+ if (flags & XBOARD)
+ return;
+ if (!(flags & POST))
+ return;
+ if (NodeCnt < 500000 && (flags & SOLVE)) {
+ return;
+ }
+ SANMove (p->move, ply);
+ printf ("\r%2d. %2d/%2d%10s ", Idepth,
+ (int) (p-TreePtr[ply]+1), (int) (TreePtr[ply+1]-TreePtr[ply]), SANmv);
+ fflush (stdout);
+}
+
+static int ply1score;
+
+int SearchRoot (short depth, int alpha, int beta)
+/**************************************************************************
+ *
+ * This perform searches at ply=1. For ply>1, it calls the more generic
+ * search() routine. The rationale for splitting these is because at
+ * ply==1, things are done slightly differently than from the other plies,
+ * e.g. print PVs, not testing null move etc.
+ *
+ **************************************************************************/
+{
+ int best, score, savealpha;
+ uint8_t side, xside, ply;
+ short nodetype;
+ leaf *p, *pbest;
+
+ ply = 1;
+ side = board.side;
+ xside = 1^side;
+ ChkCnt[2] = ChkCnt[1];
+ ThrtCnt[2] = ThrtCnt[1];
+ KingThrt[white][ply] = MateScan (white);
+ KingThrt[black][ply] = MateScan (black);
+ InChk[ply] = SqAtakd (board.king[side], xside);
+ if (InChk[ply] && ChkCnt[ply] < 3*Idepth)
+ {
+ ChkExtCnt++;
+ ChkCnt[ply+1]++;
+ depth += 1;
+ }
+ best = -INFINITY;
+ savealpha = alpha;
+ nodetype = PV;
+ pbest = NULL;
+
+ for (p = TreePtr[1]; p < TreePtr[2]; p++)
+ {
+ pick (p, 1);
+ ShowThinking (p, ply);
+ MakeMove (side, &p->move);
+ NodeCnt++;
+
+ /* If first move, search against full alpha-beta window */
+ if (p == TreePtr[1])
+ {
+ score = -Search (2, depth-1, -beta, -alpha, nodetype);
+ /*
+ The following occurs when we are re-searching a fail high move
+ and now it has fail low. This can be disastrous, so immediately
+ adjust alpha and research.
+ */
+ if (beta == INFINITY && score <= alpha)
+ {
+ alpha = -INFINITY;
+ score = -Search (2, depth-1, -beta, -alpha, nodetype);
+ }
+ }
+
+ /* Else search against zero window */
+ else
+ {
+ nodetype = CUT;
+ alpha = MAX (best, alpha);
+ score = -Search (2, depth-1, -alpha-1, -alpha, nodetype);
+ if (score > best)
+ {
+ if (alpha < score && score < beta)
+ {
+ nodetype = PV;
+ score = -Search (2, depth-1, -beta, -score, nodetype);
+ }
+ }
+ }
+ UnmakeMove (xside, &p->move);
+
+ ply1score = p->score = score;
+ if (score > best)
+ {
+ best = score;
+ pbest = p;
+ if (best > alpha)
+ {
+ rootscore = best;
+ RootPV = p->move;
+ if (best >= beta)
+ goto done;
+ ShowLine (RootPV, best, '&');
+ }
+ }
+
+ if (flags & TIMEOUT)
+ {
+ /* ply == 1 always at this point, but code
+ * copied from Search
+ */
+ best = (ply & 1 ? rootscore : -rootscore );
+ return (best);
+ }
+
+ if (((flags & PONDER) || SearchDepth == 0) && (NodeCnt & TIMECHECK) == 0)
+ {
+ if (flags & PONDER) {
+ if (input_status != INPUT_NONE)
+ SET(flags, TIMEOUT);
+ } else {
+ ElapsedTime = GetElapsed (StartTime);
+ if ((ElapsedTime >= SearchTime && (
+ rootscore == -INFINITY-1
+ || ply1score > lastrootscore - 25
+ || flags & SOLVE))
+ || ElapsedTime >= maxtime)
+ SET (flags, TIMEOUT);
+ }
+ }
+
+ if (MATE+1 == best+1)
+ return (best);
+ }
+
+/* If none of the move is good, we still want to try the same first move */
+ if (best <= savealpha)
+ TreePtr[1]->score = savealpha;
+
+/*****************************************************************************
+ *
+ * Out of main search loop.
+ *
+ *****************************************************************************/
+done:
+
+ /* Update history */
+ if (best > savealpha)
+ history[side][pbest->move & 0x0FFF] += HISTSCORE(depth);
+
+ rootscore = best;
+ return (best);
+}
+
+
+int Search (uint8_t ply, short depth, int alpha, int beta, short nodetype)
+/**************************************************************************
+ *
+ * The basic algorithm for this search routine came from Anthony
+ * Marsland. It is a PVS (Principal Variation Search) algorithm.
+ * The fail-soft alpha-beta technique is also used for improved
+ * pruning.
+ *
+ **************************************************************************/
+{
+ int best, score, nullscore, savealpha;
+ int side, xside;
+ int rc, t0, t1, firstmove;
+ int fcut, fdel, donull, savenode, extend;
+ leaf *p, *pbest;
+ int g0, g1;
+ int upperbound;
+
+ /* Check if this position is a known draw */
+ if (EvaluateDraw ())
+ return (DRAWSCORE);
+ if (GameCnt >= Game50+3 && Repeat())
+ {
+ RepeatCnt++;
+ return (DRAWSCORE);
+ }
+
+ side = board.side;
+ xside = 1^side;
+ donull = true;
+
+/*************************************************************************
+ *
+ * Perform some basic search extensions.
+ * 1. One reply extensions.
+ * 2. If in check, extend (maximum of Idepth-1).
+ * 3. If there is a threat to the King, extend (not beyond 2*Idepth)
+ * 4. If recapture to same square and not beyond Idepth+2
+ * 5. If pawn move to 7th rank at the leaf node, extend.
+ *
+ *************************************************************************/
+ extend = false;
+ InChk[ply] = SqAtakd (board.king[side], xside);
+ if (InChk[ply])
+ {
+ TreePtr[ply+1] = TreePtr[ply];
+ GenCheckEscapes (ply);
+ if (TreePtr[ply] == TreePtr[ply+1])
+ return (-MATE+ply-2);
+ if (TreePtr[ply]+1 == TreePtr[ply+1])
+ {
+ depth += 1;
+ extend = true;
+ OneRepCnt++;
+ }
+ }
+
+/*
+ We've already found a mate at the next ply. If we aren't being mated by
+ a shorter line, so just return the current material value.
+*/
+ if (rootscore + ply >= MATE)
+ return (MATERIAL);
+
+ g0 = Game[GameCnt].move;
+ g1 = GameCnt > 0 ? Game[GameCnt-1].move : 0;
+ t0 = TOSQ(g0);
+ t1 = TOSQ(g1);
+ ChkCnt[ply+1] = ChkCnt[ply];
+ ThrtCnt[ply+1] = ThrtCnt[ply];
+ KingThrt[white][ply] = MateScan (white);
+ KingThrt[black][ply] = MateScan (black);
+ if (InChk[ply] && /* ChkCnt[ply] < Idepth-1*/ ply <= 2*Idepth)
+ {
+ ChkExtCnt++;
+ ChkCnt[ply+1]++;
+ depth += 1;
+ extend = true;
+ }
+ else if (!KingThrt[side][ply-1] && KingThrt[side][ply] && ply <= 2*Idepth)
+ {
+ KingExtCnt++;
+ extend = true;
+ depth += 1;
+ extend = true;
+ donull = false;
+ }
+ /* Promotion extension */
+ else if (g0 & PROMOTION)
+ {
+ PawnExtCnt++;
+ depth += 1; /* Not reached, but why?! */
+ extend = true;
+ }
+ /* Recapture extension */
+ else if ((g0 & CAPTURE) && (board.material[computer] -
+ board.material[1^computer] == RootMaterial))
+ {
+ RcpExtCnt++;
+ depth += 1;
+ extend = true;
+ }
+ /* 6th or 7th rank extension */
+ else if (depth <= 1 && cboard[t0] == pawn && (RANK(t0) == rank7[xside] || RANK(t0) == rank6[xside]))
+ {
+ PawnExtCnt++;
+ depth += 1;
+ extend = true;
+ }
+
+/****************************************************************************
+ *
+ * The following extension is to handle cases when the opposing side is
+ * delaying the mate by useless interposing moves.
+ *
+ ****************************************************************************/
+ if (ply > 2 && InChk[ply-1] && cboard[t0] != king && t0 != t1 &&
+ !SqAtakd (t0, xside))
+ {
+ HorzExtCnt++;
+ depth += 1;
+ extend = true;
+ }
+
+/***************************************************************************
+ *
+ * This is a new code to perform search reductiion. We introduce some
+ * form of selectivity here.
+ *
+ **************************************************************************/
+
+ if (depth <= 0)
+ return (Quiesce (ply, alpha, beta));
+
+/****************************************************************************
+ *
+ * Probe the transposition table for a score and a move.
+ * If the score is an upperbound, then we can use it to improve the value
+ * of beta. If a lowerbound, we improve alpha. If it is an exact score,
+ * if we now get a cut-off due to the new alpha/beta, return the score.
+ *
+ ***************************************************************************/
+ Hashmv[ply] = 0;
+ upperbound = INFINITY;
+ if (flags & USEHASH)
+ {
+ rc = TTGet (side, depth, ply, &score, &g1);
+ if (rc)
+ {
+ Hashmv[ply] = g1 & MOVEMASK;
+ switch (rc)
+ {
+ case POORDRAFT : /* Not reached */ break;
+ case EXACTSCORE : /* Not reached */ return (score);
+ case UPPERBOUND : beta = MIN (beta, score);
+ upperbound = score;
+ donull = false;
+ break;
+ case LOWERBOUND : /*alpha = MAX (alpha, score);*/
+ alpha = score;
+ break;
+ case QUIESCENT : Hashmv[ply] = 0;
+ break;
+ default : break;
+ }
+ if (alpha >= beta)
+ return (score);
+ }
+ }
+
+/*****************************************************************************
+ *
+ * Perform the null move here. There are certain cases when null move
+ * is not done.
+ * 1. When the previous move is a null move.
+ * 2. At the frontier (depth == 1)
+ * 3. At a PV node.
+ * 4. If side to move is in check.
+ * 5. If the material score + pawn value is still below beta.
+ * 6. If we are being mated at next ply.
+ * 7. If hash table indicate the real score is below beta (UPPERBOUND).
+ * 8. If side to move has less than or equal to a bishop in value.
+ * 9. If Idepth <= 3. This allows us to find mate-in 2 problems quickly.
+ * 10. We are looking for a null threat.
+ *
+ *****************************************************************************/
+ if (ply > 4 && InChk[ply-2] && InChk[ply-4])
+ donull = false;
+ if (flags & USENULL && g0 != NULLMOVE && depth > 1 && nodetype != PV &&
+ !InChk[ply] && MATERIAL+ValueP > beta && beta > -MATE+ply && donull &&
+ board.pmaterial[side] > ValueB )
+ {
+ TreePtr[ply+1] = TreePtr[ply];
+ MakeNullMove (side);
+ nullscore = -Search (ply+1, depth-3, -beta, -beta+1, nodetype);
+ UnmakeNullMove (xside);
+ if (nullscore >= beta)
+ {
+ NullCutCnt++;
+ return (nullscore);
+ }
+ if ( depth-3 >= 1 && MATERIAL > beta && nullscore <= -MATE+256)
+ {
+ depth += 1;
+ extend = true;
+ }
+ }
+
+ if (InChk[ply] && TreePtr[ply]+1 < TreePtr[ply+1])
+ SortMoves (ply);
+
+ pickphase[ply] = PICKHASH;
+ GETNEXTMOVE;
+
+/*************************************************************************
+ *
+ * Razoring + Futility.
+ * At depth 3, if there is no extensions and we are really bad, decrease
+ * the search depth by 1.
+ * At depth 2, if there is no extensions and we are quite bad, then we
+ * prune all non checking moves and capturing moves that don't bring us up
+ * back to alpha.
+ * Caveat: Skip all this if we are in the ending.
+ *
+ *************************************************************************/
+ fcut = false;
+ fdel = MAX (ValueQ, maxposnscore[side]);
+ if (!extend && nodetype != PV && depth == 3 && FUTSCORE <= alpha)
+ {
+ depth = 2;
+ RazrCutCnt++;
+ }
+ fdel = MAX (ValueR, maxposnscore[side]);
+ fcut = (!extend && nodetype != PV && depth == 2 && FUTSCORE <= alpha);
+ if (!fcut)
+ {
+ fdel = MAX (3*ValueP, maxposnscore[side]);
+ fcut = (nodetype != PV && depth == 1 && FUTSCORE <= alpha);
+ }
+
+ MakeMove (side, &p->move);
+ NodeCnt++;
+ g0 = g1 = 0;
+ while ((g0 = SqAtakd (board.king[side], xside)) > 0 ||
+ (fcut && FUTSCORE < alpha && !SqAtakd (board.king[xside], side) &&
+ !MateScan (xside)))
+ {
+ if (g0 == 0) g1++;
+ UnmakeMove (xside, &p->move);
+ if (GETNEXTMOVE == false)
+ return (g1 ? Evaluate(alpha,beta) : DRAWSCORE);
+ MakeMove (side, &p->move);
+ NodeCnt++;
+ }
+ firstmove = true;
+ pbest = p;
+ best = -INFINITY;
+ savealpha = alpha;
+ nullscore = INFINITY;
+ savenode = nodetype;
+ if (nodetype != PV)
+ nodetype = (nodetype == CUT) ? ALL : CUT;
+
+ while (1)
+ {
+ /* We have already made the move before the loop. */
+ if (firstmove)
+ {
+ firstmove = false;
+ score = -Search (ply+1, depth-1, -beta, -alpha, nodetype);
+ }
+
+ /* Zero window search for rest of moves */
+ else
+ {
+ if (GETNEXTMOVE == false)
+ break;
+
+ MakeMove (side, &p->move);
+ NodeCnt++;
+ if (SqAtakd (board.king[side], xside))
+ {
+ UnmakeMove (xside, &p->move);
+ continue;
+ }
+
+/*****************************************************************************
+ *
+ * Futility pruning. The idea is that at the frontier node (depth == 1),
+ * if the side on the move is materially bad, then if the move doesn't win
+ * back material or the move isn't a check or doesn't threatened the king,
+ * then there is no point in searching this move. So skip it.
+ * Caveat: However if the node is a PV, we skip this test.
+ *
+ *****************************************************************************/
+ if (fcut && FUTSCORE <= alpha && !SqAtakd (board.king[xside], side) &&
+ !MateScan (xside))
+
+ {
+ UnmakeMove (xside, &p->move);
+ FutlCutCnt++;
+ NodeCnt--;
+ continue;
+ }
+ NodeCnt++;
+
+ if (nodetype == PV)
+ nodetype = CUT;
+ alpha = MAX (best, alpha); /* fail-soft condition */
+ score = -Search (ply+1, depth-1, -alpha-1, -alpha, nodetype);
+ if (score > best)
+ {
+ if (savenode == PV)
+ nodetype = PV;
+ if (alpha < score && score < beta)
+ {
+ score = -Search (ply+1, depth-1, -beta, -score, nodetype);
+ }
+ if (nodetype == PV && score <= alpha &&
+ Game[GameCnt+1].move == NULLMOVE)
+ {
+ score = -Search (ply+1, depth-1, -alpha, INFINITY, nodetype);
+ }
+ }
+ }
+
+ UnmakeMove (xside, &p->move);
+
+ if (score > best)
+ {
+ best = score;
+ pbest = p;
+ if (best >= beta)
+ goto done;
+ }
+
+ if (flags & TIMEOUT)
+ {
+ best = (ply & 1 ? rootscore : -rootscore);
+ return (best);
+ }
+
+ if (((flags & PONDER) || SearchDepth == 0) && (NodeCnt & TIMECHECK) == 0)
+ {
+ if (flags & PONDER) {
+ if (input_status != INPUT_NONE)
+ SET(flags, TIMEOUT);
+ } else {
+ ElapsedTime = GetElapsed (StartTime);
+ if ((ElapsedTime >= SearchTime &&
+ (rootscore == -INFINITY-1 ||
+ ply1score > lastrootscore - 25 || flags & SOLVE)) ||
+ ElapsedTime >= maxtime)
+ SET (flags, TIMEOUT);
+ }
+ }
+
+/* The following line should be explained as I occasionally forget too :) */
+/* This code means that if at this ply, a mating move has been found, */
+/* then we can skip the rest of the moves! */
+ if (MATE+1 == best+ply)
+ goto done;
+ }
+
+/*****************************************************************************
+ *
+ * Out of main search loop.
+ *
+ *****************************************************************************/
+done:
+
+/*
+ if (upperbound < best)
+ printf ("Inconsistencies %d %d\n", upperbound, best);
+*/
+
+ /* Save the best move inside the transposition table */
+ if (flags & USEHASH){
+/*
+ * Nasty temporary hack to try and work around timeout problem
+ * If we are pondering and timeout don't save incomplete answers
+ * Must look at failure of TIMEOUT condition more carefully!
+ */
+ if ( !(flags & TIMEOUT))
+ TTPut (side, depth, ply, savealpha, beta, best, pbest->move);
+ }
+
+ /* Update history */
+ if (best > savealpha)
+ history[side][pbest->move & 0x0FFF] += HISTSCORE(depth);
+
+ /* Don't store captures as killers as they are tried before killers */
+ if (!(pbest->move & (CAPTURE | PROMOTION)) && best > savealpha)
+ {
+ if (killer1[ply] == 0)
+ killer1[ply] = pbest->move & MOVEMASK;
+ else if ((pbest->move & MOVEMASK) != killer1[ply])
+ killer2[ply] = pbest->move & MOVEMASK;
+ }
+
+ return (best);
+}
+
+
+void ShowLine (int move __attribute__ ((unused)), int score, char c)
+/*****************************************************************************
+ *
+ * Print out the latest PV found during the search.
+ * The only move we know is the root move. The rest of the PV is taken
+ * from the hash table. This strategy avoids all the headaches associated
+ * with returning the PV up from the leaf to the root.
+ *
+ *****************************************************************************/
+{
+ int i, len;
+ int pvar[MAXPLYDEPTH];
+
+ /* SMC */
+ if (!(flags & POST))
+ return;
+ if (NodeCnt < 500000 && (flags & SOLVE)) {
+ /* printf("NodeCnt = %d\n",NodeCnt); getchar(); */
+ return;
+ }
+ if (Idepth == 1 && c == '&')
+ return;
+ if ((flags & XBOARD) && c == '&')
+ return;
+ if (rootscore == -INFINITY-1)
+ return;
+ ElapsedTime = GetElapsed (StartTime);
+
+ /*
+ * The different output formats for Xboard and GNU Chess are documented
+ * in the engine protocol guide.
+ *
+ * In particular if the character after ply is not a space, Xboard
+ * assume it is talking to a GNU Chess compatible engine and
+ * uses time in seconds, not centiseconds.
+ *
+ * This code should be simplified!
+ *
+ */
+ if (flags & XBOARD) {
+ if (score > MATE-255) {
+ printf ("%d%c Mat%d %d %ld\t", Idepth, c,
+ (int)(MATE+2-abs(score))/2, (int)(ElapsedTime), NodeCnt+QuiesCnt);
+ if (ofp != stdout)
+ fprintf (ofp,"%2d%c%7.2f Mat%02d%10ld\t", Idepth, c, ElapsedTime,
+ (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
+ } else if (score < -MATE+255) {
+ printf ("%d%c -Mat%2d %d %ld\t", Idepth, c,
+ (int)(MATE+2-abs(score))/2, (int)(ElapsedTime), NodeCnt+QuiesCnt);
+ if (ofp != stdout)
+ fprintf (ofp,"%2d%c%7.2f -Mat%02d%10ld\t", Idepth, c, ElapsedTime,
+ (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
+ } else {
+ printf ("%d%c %d %d %ld\t", Idepth, c, (int)score,
+ (int)(ElapsedTime), NodeCnt+QuiesCnt);
+ if (ofp != stdout)
+ fprintf (ofp,"%2d%c%7.2f%7d%10ld\t", Idepth, c,
+ ElapsedTime, score, NodeCnt+QuiesCnt);
+ }
+ }
+ else { /* Not XBOARD */
+ if (score > MATE-255) {
+ printf ("\r%2d%c%7.2f Mat%02d%10ld\t", Idepth, c, ElapsedTime,
+ (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
+ if (ofp != stdout)
+ fprintf (ofp,"\r%2d%c%7.2f Mat%02d%10ld\t", Idepth, c, ElapsedTime,
+ (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
+ } else if (score < -MATE+255) {
+ printf ("\r%2d%c%7.2f -Mat%02d%10ld\t", Idepth, c, ElapsedTime,
+ (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
+ if (ofp != stdout)
+ fprintf (ofp,"\r%2d%c%7.2f -Mat%02d%10ld\t", Idepth, c, ElapsedTime,
+ (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
+ } else {
+ printf ("\r%2d%c%7.2f%7d%10ld\t", Idepth, c, ElapsedTime,
+ score, NodeCnt+QuiesCnt);
+ if (ofp != stdout)
+ fprintf (ofp,"\r%2d%c%7.2f%7d%10ld\t", Idepth, c, ElapsedTime,
+ score, NodeCnt+QuiesCnt);
+ }
+ }
+
+ if (c == '-')
+ {
+ printf ("\n");
+ if (ofp != stdout) fprintf(ofp, "\n");
+ return;
+ }
+ else if (c == '+')
+ {
+ SANMove (RootPV, 1);
+ printf (" %s\n", SANmv);
+ if (ofp != stdout) fprintf (ofp," %s\n", SANmv);
+ return;
+ }
+
+ SANMove (RootPV, 1);
+ printf (" %s", SANmv);
+ if (ofp != stdout) fprintf (ofp," %s", SANmv);
+ MakeMove (board.side, &RootPV);
+ TreePtr[3] = TreePtr[2];
+ GenMoves (2);
+ len = strlen (SANmv);
+ i = 2;
+ pvar[1] = RootPV;
+
+ /* We fill the rest of the PV with moves from the hash table */
+ if ((flags & USEHASH))
+ {
+ while (TTGetPV (board.side, i, rootscore, &pvar[i]))
+ {
+ if ((MATESCORE(score) && abs(score) == MATE+2-i) || Repeat ())
+ break;
+
+ if (len >= 32)
+ {
+ printf ("\n\t\t\t\t");
+ if (ofp != stdout) fprintf (ofp,"\n\t\t\t\t");
+ len = 0;
+ }
+ SANMove (pvar[i], i);
+ printf (" %s", SANmv);
+ if (ofp != stdout) fprintf (ofp," %s", SANmv);
+ MakeMove (board.side, &pvar[i]);
+ TreePtr[i+2] = TreePtr[i+1];
+ GenMoves (++i);
+ len += strlen (SANmv);
+ }
+ }
+
+ printf ("\n");
+ if (ofp != stdout) fprintf(ofp,"\n");
+ for (--i; i; i--)
+ UnmakeMove (board.side, &pvar[i]);
+ fflush (stdout);
+ if (ofp != stdout) fflush (ofp);
+}
diff --git a/src/chess_computer-activity/gnuchess/solve.c b/src/chess_computer-activity/gnuchess/solve.c
new file mode 100644
index 0000000..9d71914
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/solve.c
@@ -0,0 +1,78 @@
+/* GNU Chess 5.0 - solve.c - position solving code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+
+
+void Solve (char *file)
+/*****************************************************************************
+ *
+ *
+ *
+ *****************************************************************************/
+{
+ int total, correct, found;
+ long TotalNodes;
+ char *p;
+
+ total = correct = 0;
+ TotalNodes = 0;
+ SET (flags, SOLVE);
+ while (ReadEPDFile (file, 0))
+ {
+ NewPosition ();
+ total++;
+ ShowBoard ();
+ Iterate ();
+ TotalNodes += NodeCnt + QuiesCnt;
+ p = solution;
+ found = false;
+ while (*p != '\0')
+ {
+ if (!strncmp (p, SANmv, strlen(SANmv)))
+ {
+ correct++;
+ found = true;
+ break;
+ }
+ while (*p != ' ' && *p != '\0') p++;
+ while (*p == ' ' && *p != '\0') p++;
+ }
+ printf ("%s : ", id);
+ printf (found ? "Correct: " : "Incorrect: ");
+ printf ("%s %s\n", SANmv, solution);
+ printf ("Correct=%d Total=%d\n", correct, total);
+ }
+ printf ("\nTotal nodes = %ld\n", TotalNodes);
+ CLEAR (flags, SOLVE);
+}
+
diff --git a/src/chess_computer-activity/gnuchess/sort.c b/src/chess_computer-activity/gnuchess/sort.c
new file mode 100644
index 0000000..ea41e1c
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/sort.c
@@ -0,0 +1,345 @@
+/* GNU Chess 5.0 - sort.c - move sorting code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+
+#include "common.h"
+
+#define WEIGHT 12
+#define HASHSORTSCORE INFINITY
+#define KILLERSORTSCORE 1000
+#define CASTLINGSCORE 500
+
+void SortCaptures (int ply)
+/***************************************************************************
+ *
+ * Actually no sorting is done. Just scores are assigned to the captures.
+ * When we need a move, we will select the highest score move from the
+ * list, place it at the top and try it. This move might give us a cut
+ * in which case, there is no reason to sort.
+ *
+ ***************************************************************************/
+{
+ leaf *p;
+ int temp, f, t;
+
+ for (p = TreePtr[ply]; p < TreePtr[ply+1]; p++)
+ {
+ f = Value[cboard[FROMSQ(p->move)]];
+ t = Value[cboard[TOSQ(p->move)]];
+ if (f < t)
+ p->score = t - f;
+ else
+ {
+ temp = SwapOff (p->move);
+ p->score = (temp < 0 ? -INFINITY : temp);
+ }
+
+ }
+}
+
+
+void SortMoves (int ply)
+/*****************************************************************************
+ *
+ * Sort criteria is as follows.
+ * 1. The move from the hash table
+ * 2. Captures as above.
+ * 3. Killers.
+ * 4. History.
+ * 5. Moves to the centre.
+ *
+ *****************************************************************************/
+{
+ leaf *p;
+ int f, t, m, tovalue;
+ int side, xside;
+ BitBoard enemyP;
+
+ side = board.side;
+ xside = 1^side;
+ enemyP = board.b[xside][pawn];
+
+ for (p = TreePtr[ply]; p < TreePtr[ply+1]; p++)
+ {
+ p->score = -INFINITY;
+ f = FROMSQ (p->move);
+ t = TOSQ (p->move);
+ m = p->move & MOVEMASK;
+
+ /* Hash table move (highest score) */
+ if (m == Hashmv[ply])
+ p->score += HASHSORTSCORE;
+
+ else if (cboard[t] != 0 || p->move & PROMOTION)
+ {
+
+ /* ***** SRW My Interpretation of this code *************
+ * Captures normally in other places but..... *
+ * *
+ * On capture we generally prefer to capture with the *
+ * with the lowest value piece so to chose between *
+ * pieces we should subtract the piece value .... but *
+ * *
+ * The original code was looking at some captures *
+ * last, especially where the piece was worth more *
+ * than the piece captured - KP v K in endgame.epd *
+ * *
+ * So code modified to prefer any capture by adding *
+ * ValueK *
+ ****************************************************** */
+
+ tovalue = (Value[cboard[t]] + Value[PROMOTEPIECE (p->move)]);
+ p->score += tovalue + ValueK - Value[cboard[f]];
+
+
+ }
+ /* Killers */
+ else if (m == killer1[ply] || m == killer2[ply])
+ p->score += KILLERSORTSCORE;
+ else if (ply > 2 && (m == killer1[ply-2] || m == killer2[ply-2]))
+ p->score += KILLERSORTSCORE;
+
+ p->score += history[side][(p->move & 0x0FFF)] + taxicab[f][D5] - taxicab[t][E4];
+
+ if ( cboard[f] == pawn ) {
+ /* Look at pushing Passed pawns first */
+ if ( (enemyP & PassedPawnMask[side][t]) == NULLBITBOARD )
+ p->score +=50;
+ }
+ }
+}
+
+
+void SortRoot (void)
+/*****************************************************************************
+ *
+ * Sort the moves at the root. The heuristic is simple. Try captures/
+ * promotions first. Other moves are ordered based on their swapoff values.
+ *
+ *****************************************************************************/
+{
+ leaf *p;
+ int f, t ;
+ int side, xside;
+ BitBoard enemyP;
+
+ side = board.side;
+ xside = 1^side;
+ enemyP = board.b[xside][pawn];
+
+ for (p = TreePtr[1]; p < TreePtr[2]; p++)
+ {
+ f = Value[cboard[FROMSQ(p->move)]];
+ if (cboard[TOSQ(p->move)] != 0 || (p->move & PROMOTION))
+ {
+ t = Value[cboard[TOSQ(p->move)]];
+ if (f < t)
+ p->score = -1000 + t - f;
+ else
+ p->score = -1000 + SwapOff (p->move);
+ }
+ else
+ p->score = -3000 + SwapOff (p->move);
+
+ p->score += taxicab[FROMSQ(p->move)][D5] - taxicab[TOSQ(p->move)][E4];
+
+ if ( f == ValueP ) {
+ /* Look at pushing Passed pawns first */
+ if ( (enemyP & PassedPawnMask[side][TOSQ(p->move)]) == NULLBITBOARD )
+ p->score +=50;
+ }
+ }
+}
+
+
+void pick (leaf *head, short ply)
+/***************************************************************************
+ *
+ * This pick routine searches the movelist and swap the high score entry
+ * with the one currently at the head.
+ *
+ ***************************************************************************/
+{
+ int best;
+ leaf *p, *pbest, tmp;
+
+ best = head->score;
+ pbest = head;
+ for (p = head+1; p < TreePtr[ply+1]; p++)
+ {
+ if (p->score > best)
+ {
+ pbest = p;
+ best = p->score;
+ }
+ }
+
+ /* Swap pbest with the head */
+ tmp = *head;
+ *head = *pbest;
+ *pbest = tmp;
+}
+
+
+int PhasePick (leaf **p1, int ply)
+/***************************************************************************
+ *
+ * A phase style routine which returns the next move to the search.
+ * Hash move is first returned. If it doesn't fail high, captures are
+ * generated, sorted and tried. If no fail high still occur, the rest of
+ * the moves are generated and tried.
+ * The idea behind all this is to save time generating moves which might
+ * not be needed.
+ * CAVEAT: To implement this, the way that genmoves & friends are called
+ * have to be modified. In particular, TreePtr[ply+1] = TreePtr[ply] must
+ * be set before the calls can be made.
+ * If the board ever gets corrupted during the search, then there is a bug
+ * in IsLegalMove() which has to be fixed.
+ *
+ ***************************************************************************/
+{
+ static leaf* p[MAXPLYDEPTH];
+ leaf *p2;
+ int mv;
+ int side;
+
+ side = board.side;
+ switch (pickphase[ply])
+ {
+ case PICKHASH:
+ TreePtr[ply+1] = TreePtr[ply];
+ pickphase[ply] = PICKGEN1;
+ if (Hashmv[ply] && IsLegalMove (Hashmv[ply]))
+ {
+ TreePtr[ply+1]->move = Hashmv[ply];
+ *p1 = TreePtr[ply+1]++;
+ return (true);
+ }
+
+ case PICKGEN1:
+ pickphase[ply] = PICKCAPT;
+ p[ply] = TreePtr[ply+1];
+ GenCaptures (ply);
+ for (p2 = p[ply]; p2 < TreePtr[ply+1]; p2++)
+ p2->score = SwapOff(p2->move) * WEIGHT +
+ Value[cboard[TOSQ(p2->move)]];
+
+ case PICKCAPT:
+ while (p[ply] < TreePtr[ply+1])
+ {
+ pick (p[ply], ply);
+ if ((p[ply]->move & MOVEMASK) == Hashmv[ply])
+ {
+ p[ply]++;
+ continue;
+ }
+ *p1 = p[ply]++;
+ return (true);
+ }
+
+ case PICKKILL1:
+ pickphase[ply] = PICKKILL2;
+ if (killer1[ply] && killer1[ply] != Hashmv[ply] &&
+ IsLegalMove (killer1[ply]))
+ {
+ TreePtr[ply+1]->move = killer1[ply];
+ *p1 = TreePtr[ply+1];
+ TreePtr[ply+1]++;
+ return (true);
+ }
+
+ case PICKKILL2:
+ pickphase[ply] = PICKGEN2;
+ if (killer2[ply] && killer2[ply] != Hashmv[ply] &&
+ IsLegalMove (killer2[ply]))
+ {
+ TreePtr[ply+1]->move = killer2[ply];
+ *p1 = TreePtr[ply+1];
+ TreePtr[ply+1]++;
+ return (true);
+ }
+
+ case PICKGEN2:
+ pickphase[ply] = PICKREST;
+ p[ply] = TreePtr[ply+1];
+ GenNonCaptures (ply);
+ for (p2 = p[ply]; p2 < TreePtr[ply+1]; p2++)
+ {
+ p2->score = history[side][(p2->move & 0x0FFF)] +
+ taxicab[FROMSQ(p2->move)][D5] - taxicab[TOSQ(p2->move)][E4];
+ if (p2->move & CASTLING)
+ p2->score += CASTLINGSCORE;
+ }
+
+ case PICKREST:
+ while (p[ply] < TreePtr[ply+1])
+ {
+ pick (p[ply], ply);
+ mv = p[ply]->move & MOVEMASK;
+ if (mv == Hashmv[ply] || mv == killer1[ply] ||
+ mv == killer2[ply])
+ {
+ p[ply]++;
+ continue;
+ }
+ *p1 = p[ply]++;
+ return (true);
+ }
+ }
+ return (false);
+}
+
+
+int PhasePick1 (leaf **p1, int ply)
+/***************************************************************************
+ *
+ * Similar to phase pick, but only used when the King is in check.
+ *
+ ***************************************************************************/
+{
+ static leaf* p[MAXPLYDEPTH];
+
+ switch (pickphase[ply])
+ {
+ case PICKHASH:
+ pickphase[ply] = PICKREST;
+ p[ply] = TreePtr[ply];
+
+ case PICKREST:
+ while (p[ply] < TreePtr[ply+1])
+ {
+ pick (p[ply], ply);
+ *p1 = p[ply]++;
+ return (true);
+ }
+ }
+ return (false);
+}
diff --git a/src/chess_computer-activity/gnuchess/swap.c b/src/chess_computer-activity/gnuchess/swap.c
new file mode 100644
index 0000000..b303cc1
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/swap.c
@@ -0,0 +1,170 @@
+/* GNU Chess 5.0 - swap.c - static exchange evaluator code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+
+static const int xray[7] = { 0, 1, 0, 1, 1, 1, 0 };
+
+int SwapOff (int move)
+/****************************************************************************
+ *
+ * A Static Exchange Evaluator (or SEE for short).
+ * First determine the target square. Create a bitboard of all squares
+ * attacking the target square for both sides. Using these 2 bitboards,
+ * we take turn making captures from smallest piece to largest piece.
+ * When a sliding piece makes a capture, we check behind it to see if
+ * another attacker piece has been exposed. If so, add this to the bitboard
+ * as well. When performing the "captures", we stop if one side is ahead
+ * and doesn't need to capture, a form of pseudo-minimaxing.
+ *
+ ****************************************************************************/
+{
+ int f, t, sq, piece, lastval;
+ int side, xside;
+ int swaplist[MAXPLYDEPTH], n;
+ BitBoard b, c, *d, *e, r;
+
+ f = FROMSQ (move);
+ t = TOSQ (move);
+ side = ((board.friends[white] & BitPosArray[f]) ? white : black);
+ xside = 1^side;
+
+ /* Squares attacking t for side and xside */
+ b = AttackTo (t, side);
+ c = AttackTo (t, xside);
+ CLEARBIT(b, f);
+ if (xray[cboard[f]])
+ AddXrayPiece (t, f, side, &b, &c);
+
+ d = board.b[side];
+ e = board.b[xside];
+ if (move & PROMOTION)
+ {
+ swaplist[0] = Value[PROMOTEPIECE (move)] - ValueP;
+ lastval = -Value[PROMOTEPIECE (move)];
+ }
+ else
+ {
+ swaplist[0] = (move & ENPASSANT ? ValueP : Value[cboard[t]]);
+ lastval = -Value[cboard[f]];
+ }
+ n = 1;
+ while (1)
+ {
+ if (c == NULLBITBOARD)
+ break;
+ for (piece = pawn; piece <= king; piece++)
+ {
+ r = c & e[piece];
+ if (r)
+ {
+ sq = leadz (r);
+ CLEARBIT (c, sq);
+ if (xray[piece])
+ AddXrayPiece (t, sq, xside, &c, &b);
+ swaplist[n] = swaplist[n-1] + lastval;
+ n++;
+ lastval = Value[piece];
+ break;
+ }
+ }
+
+ if (b == NULLBITBOARD)
+ break;
+ for (piece = pawn; piece <= king; piece++)
+ {
+ r = b & d[piece];
+ if (r)
+ {
+ sq = leadz (r);
+ CLEARBIT (b, sq);
+ if (xray[piece])
+ AddXrayPiece (t, sq, side, &b, &c);
+ swaplist[n] = swaplist[n-1] + lastval;
+ n++;
+ lastval = -Value[piece];
+ break;
+ }
+ }
+ }
+
+/****************************************************************************
+ *
+ * At this stage, we have the swap scores in a list. We just need to
+ * mini-max the scores from the bottom up to the top of the list.
+ *
+ ****************************************************************************/
+ --n;
+ while (n)
+ {
+ if (n & 1)
+ {
+ if (swaplist[n] <= swaplist[n-1])
+ swaplist[n-1] = swaplist[n];
+ }
+ else
+ {
+ if (swaplist[n] >= swaplist[n-1])
+ swaplist[n-1] = swaplist[n];
+ }
+ --n;
+ }
+ return (swaplist[0]);
+}
+
+
+void AddXrayPiece (int t, int sq, int side, BitBoard *b, BitBoard *c)
+/***************************************************************************
+ *
+ * The purpose of this routine is to find a piece which attack through
+ * another piece (e.g. two rooks, Q+B, B+P, etc.) Side is the side attacking
+ * the square where the swapping is to be done.
+ *
+ ***************************************************************************/
+{
+ int dir, nsq, piece;
+ BitBoard a;
+
+ dir = directions[t][sq];
+ a = Ray[sq][dir] & board.blocker;
+ if (a == NULLBITBOARD)
+ return;
+ nsq = (t < sq ? leadz (a) : trailz (a));
+ piece = cboard[nsq];
+ if ((piece == queen) || (piece == rook && dir > 3) ||
+ (piece == bishop && dir < 4))
+ {
+ if (BitPosArray[nsq] & board.friends[side])
+ *b |= BitPosArray[nsq];
+ else
+ *c |= BitPosArray[nsq];
+ }
+ return;
+}
diff --git a/src/chess_computer-activity/gnuchess/test.c b/src/chess_computer-activity/gnuchess/test.c
new file mode 100644
index 0000000..db340df
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/test.c
@@ -0,0 +1,266 @@
+/* GNU Chess 5.0 - test.c - testing code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#include "common.h"
+
+void TestMoveGenSpeed (void)
+/**************************************************************************
+ *
+ * This routine benchmarks the speed of the bitmap move generation.
+ * The test case is BK.epd, the 24 positions from the Brat-Kopec test
+ * suite.
+ *
+ **************************************************************************/
+{
+ unsigned long i;
+ struct timeval t1, t2;
+ double et;
+ short side, xside;
+
+ GenCnt = 0;
+ et = 0;
+/*
+ while (ReadEPDFile ("../test/wac.epd", 0))
+ {
+*/
+ gettimeofday (&t1, NULL);
+ side = board.side;
+ xside = 1^side;
+ for (i = 0; i < 2000000; i++)
+ {
+ TreePtr[2] = TreePtr[1];
+ GenMoves (1);
+ }
+ gettimeofday (&t2, NULL);
+ et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6;
+ printf ("Time = %f\n", et);
+/*
+ }
+*/
+ printf ("No. of moves generated = %lu\n", GenCnt);
+ printf ("Time taken = %f secs\n", et);
+ if (et > 0)
+ printf ("Rate = %f moves/sec.\n", GenCnt / et);
+}
+
+
+
+void TestNonCaptureGenSpeed (void)
+/**************************************************************************
+ *
+ * This routine benchmarks the speed of the bitmap move generation
+ * for non capturing moves.
+ * The test case is BK.epd, the 24 positions from the Brat-Kopec test
+ * suite.
+ *
+ **************************************************************************/
+{
+ unsigned long i;
+ struct timeval t1, t2;
+ double et;
+
+ GenCnt = 0;
+ et = 0;
+ while (ReadEPDFile ("../test/wac.epd", 0))
+ {
+ gettimeofday (&t1, NULL);
+ for (i = 0; i < 100000; i++)
+ {
+ TreePtr[2] = TreePtr[1];
+ GenNonCaptures (1);
+ }
+ gettimeofday (&t2, NULL);
+ et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6;
+ printf ("Time = %f\n", et);
+ }
+ printf ("No. of moves generated = %lu\n", GenCnt);
+ printf ("Time taken = %f\n", et);
+ if (et > 0)
+ printf ("Rate = %f\n", GenCnt / et);
+}
+
+
+void TestCaptureGenSpeed (void)
+/**************************************************************************
+ *
+ * This routine benchmarks the speed of the bitmap move generation
+ * for captures.
+ * The test case is BK.epd, the 24 positions from the Brat-Kopec test
+ * suite.
+ *
+ **************************************************************************/
+{
+ unsigned long i;
+ struct timeval t1, t2;
+ double et;
+
+ GenCnt = 0;
+ et = 0;
+ while (ReadEPDFile ("../test/wac.epd", 0))
+ {
+ gettimeofday (&t1, NULL);
+ for (i = 0; i < 200000; i++)
+ {
+ TreePtr[2] = TreePtr[1];
+ GenCaptures (1);
+ }
+ gettimeofday (&t2, NULL);
+ et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) / 1e6;
+ printf ("Time = %f\n", et);
+ }
+ printf ("No. of moves generated = %lu\n", GenCnt);
+ printf ("Time taken = %f\n", et);
+ if (et > 0)
+ printf ("Rate = %f\n", GenCnt / et);
+}
+
+
+void TestMoveList (void)
+/****************************************************************************
+ *
+ * This routine reads in a *.epd file (EPD notation) and prints the legal
+ * moves for that position.
+ *
+ ****************************************************************************/
+{
+ while (ReadEPDFile ("TEST/GMG1.epd", 0))
+ {
+ ShowBoard ();
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenMoves (1);
+ FilterIllegalMoves (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %lu\n\n", GenCnt);
+ }
+}
+
+
+void TestNonCaptureList (void)
+/****************************************************************************
+ *
+ * This routine reads in a *.epd file (EPD notation) and prints the
+ * non-capturing moves for that position.
+ *
+ ****************************************************************************/
+{
+ while (ReadEPDFile ("TEST/GMG1.epd", 0))
+ {
+ ShowBoard ();
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenNonCaptures (1);
+ FilterIllegalMoves (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %lu\n\n", GenCnt);
+ }
+}
+
+
+void TestCaptureList (void)
+/****************************************************************************
+ *
+ * This routine reads in a *.epd file (EPD notation) and prints the capture
+ * moves for that position.
+ *
+ ****************************************************************************/
+{
+ while (ReadEPDFile ("TEST/GMG1.epd", 0))
+ {
+ ShowBoard ();
+ GenCnt = 0;
+ TreePtr[2] = TreePtr[1];
+ GenCaptures (1);
+ FilterIllegalMoves (1);
+ ShowMoveList (1);
+ printf ("No. of moves generated = %lu\n\n", GenCnt);
+ }
+}
+
+
+#define NEVALS 30000
+
+void TestEvalSpeed (void)
+/***************************************************************************
+ *
+ * This routine reads in the BK.epd and test the speed of the
+ * evaluation routines.
+ *
+ ***************************************************************************/
+{
+ unsigned long i;
+ struct timeval t1, t2;
+ double et;
+
+ et = 0;
+ EvalCnt = 0;
+ while (ReadEPDFile ("../test/wac.epd", 0))
+ {
+ gettimeofday (&t1, NULL);
+ for (i = 0; i < NEVALS; i++)
+ {
+ (void) Evaluate (-INFINITY, INFINITY);
+ }
+ gettimeofday (&t2, NULL);
+ et += (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec)/1e6;
+ printf ("Time = %f\n", et);
+ }
+ printf ("No. of positions evaluated = %lu\n", EvalCnt);
+ printf ("Time taken = %f\n", et);
+ if (et > 0)
+ printf ("Rate = %f\n", EvalCnt / et);
+}
+
+
+
+void TestEval (void)
+/**************************************************************************
+ *
+ * To test the evaluation routines, read from the BK.epd test file.
+ * Print out the score. This can be improved by being more verbose
+ * and printing out salient features of the board, e.g. King safety,
+ * double bishops, rook on seventh rank, weak pawns, doubled pawns,
+ * bad bishops, passwd pawns, etc etc.
+ *
+ ***************************************************************************/
+{
+ int score;
+
+ SET (flags, TESTT);
+ while (ReadEPDFile ("../test/wac.epd", 0))
+ {
+ ShowBoard ();
+ score = Evaluate (-INFINITY, INFINITY);
+ printf (board.side == white ? "W : " : "B : ");
+ printf ("score = %d\n\n", score);
+ }
+ CLEAR (flags, TESTT);
+}
+
diff --git a/src/chess_computer-activity/gnuchess/ttable.c b/src/chess_computer-activity/gnuchess/ttable.c
new file mode 100644
index 0000000..60a4562
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/ttable.c
@@ -0,0 +1,162 @@
+/* GNU Chess 5.0 - ttable.c - transposition table code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+
+void TTPut (uint8_t side, uint8_t depth, uint8_t ply, int alpha, int beta,
+ int score, int move)
+/****************************************************************************
+ *
+ * Uses a two-tier depth-based transposition table. The criteria for
+ * replacement is as follows.
+ * 1. The first element is replaced whenever we have a position with
+ * at least the same depth. In that case the element is moved to
+ * the second slot.
+ * 2. The second slot is otherwise always replaced.
+ * Problem may be that the first elements eventually get filled with
+ * outdated entries. Might add an age counter later.
+ * The & ~1 is a trick to clear the last bit making the offset even.
+ *
+ ****************************************************************************/
+{
+ HashSlot *t;
+
+ t = HashTab[side] + ((HashKey & TTHashMask) & ~1);
+ if (depth < t->depth)
+ t++;
+ else if (t->flag)
+ *(t+1) = *t;
+
+ if (t->flag)
+ CollHashCnt++;
+ TotalPutHashCnt++;
+ t->move = move;
+ t->key = HashKey;
+ t->depth = depth;
+ if (t->depth == 0)
+ t->flag = QUIESCENT;
+ else if (score >= beta)
+ t->flag = LOWERBOUND;
+ else if (score <= alpha)
+ t->flag = UPPERBOUND;
+ else
+ t->flag = EXACTSCORE;
+
+ if (MATESCORE(score))
+ t->score = score + ( score > 0 ? ply : -ply);
+ else
+ t->score = score;
+}
+
+
+uint8_t TTGet (uint8_t side, uint8_t depth, uint8_t ply,
+ int *score, int *move)
+/*****************************************************************************
+ *
+ * Probe the transposition table. There are 2 entries to be looked at as
+ * we are using a 2-tier transposition table.
+ *
+ *****************************************************************************/
+{
+ HashSlot *t;
+
+ TotalGetHashCnt++;
+ t = HashTab[side] + ((HashKey & TTHashMask) & ~1);
+ if (HashKey != t->key && HashKey != (++t)->key)
+ return (0);
+
+ GoodGetHashCnt++;
+ *move = t->move;
+ *score = t->score;
+ if (t->depth == 0)
+ return (QUIESCENT);
+ if (t->depth < depth && !MATESCORE (t->score))
+ return (POORDRAFT);
+ if (MATESCORE(*score))
+ *score -= (*score > 0 ? ply : -ply);
+ return (t->flag);
+}
+
+
+short TTGetPV (uint8_t side, uint8_t ply, int score, int *move)
+/*****************************************************************************
+ *
+ * Probe the transposition table. There are 2 entries to be looked at as
+ * we are using a 2-tier transposition table. This routine merely wants to
+ * get the PV from the hash, nothing else.
+ *
+ *****************************************************************************/
+{
+ HashSlot *t;
+ int s;
+
+ t = HashTab[side] + ((HashKey & TTHashMask) & ~1);
+ s = t->score;
+ if (MATESCORE(s))
+ s -= (s > 0 ? ply : -ply);
+ if (HashKey == t->key && ((ply & 1 && score == s)||(!(ply & 1) && score == -s)))
+ {
+ *move = t->move;
+ return (1);
+ }
+ t++;
+ s = t->score;
+ if (MATESCORE(s))
+ s -= (s > 0 ? ply : -ply);
+ if (HashKey == t->key && ((ply & 1 && score == s)||(!(ply & 1) && score == -s)))
+ {
+ *move = t->move;
+ return (1);
+ }
+ return (0);
+}
+
+
+void TTClear (void)
+/****************************************************************************
+ *
+ * Zero out the transposition table.
+ *
+ ****************************************************************************/
+{
+ memset (HashTab[white], 0, HashSize * sizeof (HashSlot));
+ memset (HashTab[black], 0, HashSize * sizeof (HashSlot));
+}
+
+
+void PTClear (void)
+/****************************************************************************
+ *
+ * Zero out the pawn transposition table.
+ *
+ ****************************************************************************/
+{
+ memset (PawnTab[white], 0, PAWNSLOTS * sizeof (PawnSlot));
+ memset (PawnTab[black], 0, PAWNSLOTS * sizeof (PawnSlot));
+}
diff --git a/src/chess_computer-activity/gnuchess/util.c b/src/chess_computer-activity/gnuchess/util.c
new file mode 100644
index 0000000..7b89bec
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/util.c
@@ -0,0 +1,220 @@
+/* GNU Chess 5.0 - util.c - utility routine code
+ Copyright (c) 1999-2002 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+/*
+ * Endianness checks are now unnecessary
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "common.h"
+
+/*
+ * We actually do not have this configuration variable yet,
+ * should be manually added when inlining is not possible.
+ * If inlining is possible, these functions have now moved
+ * to util.h which must be included by all callers of
+ * leadz() and nbits().
+ */
+
+#ifdef NO_INLINE
+
+unsigned char leadz (BitBoard b)
+/**************************************************************************
+ *
+ * Returns the leading bit in a bitboard. Leftmost bit is 0 and
+ * rightmost bit is 63. Thanks to Robert Hyatt for this algorithm.
+ *
+ ***************************************************************************/
+{
+ if (b >> 48) return lzArray[b >> 48];
+ if (b >> 32) return lzArray[b >> 32] + 16;
+ if (b >> 16) return lzArray[b >> 16] + 32;
+ return lzArray[b] + 48;
+}
+
+unsigned char nbits (BitBoard b)
+/***************************************************************************
+ *
+ * Count the number of bits in b.
+ *
+ ***************************************************************************/
+{
+ return BitCount[b>>48] + BitCount[(b>>32) & 0xffff]
+ + BitCount[(b>>16) & 0xffff] + BitCount[b & 0xffff];
+}
+
+#endif /* NO_INLINE */
+
+void UpdateFriends (void)
+/***************************************************************************
+ *
+ * Update friend and enemy bitboard.
+ *
+ ***************************************************************************/
+{
+ register BitBoard *w, *b;
+
+ w = board.b[white];
+ b = board.b[black];
+ board.friends[white] =
+ w[pawn] | w[knight] | w[bishop] | w[rook] | w[queen] | w[king];
+ board.friends[black] =
+ b[pawn] | b[knight] | b[bishop] | b[rook] | b[queen] | b[king];
+ board.blocker = board.friends[white] | board.friends[black];
+}
+
+
+void UpdateCBoard (void)
+/**************************************************************************
+ *
+ * Updates cboard[]. cboard[i] returns the piece on square i.
+ *
+ **************************************************************************/
+{
+ BitBoard b;
+ int piece, sq;
+
+ memset (cboard, 0, sizeof (cboard));
+ for (piece = pawn; piece <= king; piece++)
+ {
+ b = board.b[white][piece] | board.b[black][piece];
+ while (b)
+ {
+ sq = leadz (b);
+ CLEARBIT (b, sq);
+ cboard[sq] = piece;
+ }
+ }
+}
+
+
+static const int OrigCboard[64] =
+{ rook, knight, bishop, queen, king, bishop, knight, rook,
+ pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
+ empty, empty, empty, empty, empty, empty, empty, empty,
+ empty, empty, empty, empty, empty, empty, empty, empty,
+ empty, empty, empty, empty, empty, empty, empty, empty,
+ empty, empty, empty, empty, empty, empty, empty, empty,
+ pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
+ rook, knight, bishop, queen, king, bishop, knight, rook };
+
+void UpdateMvboard (void)
+/**************************************************************************
+ *
+ * Updates Mvboard[]. Mvboard[i] returns the number of times the piece
+ * on square i have moved. When loading from EPD, if a piece is not on
+ * its original square, set it to 1, otherwise set to 0.
+ *
+ **************************************************************************/
+{
+ int sq;
+
+ for (sq = 0; sq < 64; sq++)
+ {
+ if (cboard[sq] == empty || cboard[sq] == OrigCboard[sq])
+ Mvboard[sq] = 0;
+ else
+ Mvboard[sq] = 1;
+ }
+}
+
+
+void EndSearch (int sig __attribute__ ((unused)) )
+/***************************************************************************
+ *
+ * User has pressed Ctrl-C. Just set flags TIMEOUT to be true.
+ *
+ ***************************************************************************/
+{
+ SET (flags, TIMEOUT);
+ signal (SIGINT, EndSearch);
+}
+
+
+short ValidateBoard (void)
+/***************************************************************************
+ *
+ * Check the board to make sure that its valid. Some things to check are
+ * a. Both sides have only 1 king.
+ * b. Side not on the move must not be in check.
+ * c. If en passant square is set, check it is possible.
+ * d. Check if castling status are all correct.
+ *
+ ***************************************************************************/
+{
+ int side, xside, sq;
+
+ if (nbits (board.b[white][king]) != 1)
+ return (false);
+ if (nbits (board.b[black][king]) != 1)
+ return (false);
+
+ side = board.side;
+ xside = 1^side;
+ if (SqAtakd (board.king[xside], side))
+ return (false);
+
+ if (board.ep > -1)
+ {
+ sq = board.ep + (xside == white ? 8 : -8);
+ if (!(BitPosArray[sq] & board.b[xside][pawn]))
+ return (false);
+ }
+
+ if (board.flag & WKINGCASTLE)
+ {
+ if (!(BitPosArray[E1] & board.b[white][king]))
+ return (false);
+ if (!(BitPosArray[H1] & board.b[white][rook]))
+ return (false);
+ }
+ if (board.flag & WQUEENCASTLE)
+ {
+ if (!(BitPosArray[E1] & board.b[white][king]))
+ return (false);
+ if (!(BitPosArray[A1] & board.b[white][rook]))
+ return (false);
+ }
+ if (board.flag & BKINGCASTLE)
+ {
+ if (!(BitPosArray[E8] & board.b[black][king]))
+ return (false);
+ if (!(BitPosArray[H8] & board.b[black][rook]))
+ return (false);
+ }
+ if (board.flag & BQUEENCASTLE)
+ {
+ if (!(BitPosArray[E8] & board.b[black][king]))
+ return (false);
+ if (!(BitPosArray[A8] & board.b[black][rook]))
+ return (false);
+ }
+
+ return (true);
+}
diff --git a/src/chess_computer-activity/gnuchess/version.h b/src/chess_computer-activity/gnuchess/version.h
new file mode 100644
index 0000000..ae6bc01
--- /dev/null
+++ b/src/chess_computer-activity/gnuchess/version.h
@@ -0,0 +1,27 @@
+/* GNU Chess 5.0 - version.h - version information symbolic definitions
+ Copyright (c) 1999 Free Software Foundation, Inc.
+
+ GNU Chess is based on the two research programs
+ Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
+
+ GNU Chess 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, or (at your option)
+ any later version.
+
+ GNU Chess 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 Chess; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Contact Info:
+ bug-gnu-chess gnu org
+ cracraft ai mit edu, cracraft stanfordalumni org, cracraft earthlink net
+*/
+#define PROGRAM "GNU Chess for GNOME"
+#define AUTHOR "Chua Kong Sian / Stuart Cracraft"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]