		Arasan - Chess for Windows - version 3.2
			Programmer's Guide

			   by Jon Dart

Arasan is a chess program for Windows 95 and Windows NT.  It is
copyrighted but under terms that allow free distribution for
non-commercial purposes. 

This archive contains the source code for Arasan. It does not contain
executables for the chess program - they are in a separate archive.

I am providing the source code for the use of programmers who may
wish to understand how the program works or to modify it for their
own use.  However, you may not distribute a modified version of this
program without the consent of the original author.

Arasan is written in C++ and was compiled with Microsoft Visual C++
version 4.1, using the Microsoft Foundation Classes (MFC).  Note:
version 3.0 requires Windows 95 or Windows NT.  It cannot be built or
run under Windows 3.1. 

The remainder of this file contains information for use by programmers
reading or working on Arasan source code.  I assume that you have a 
working familiarity with C++, Windows programming, and the Microsoft
compiler and tools.


Building Arasan

The source distribution for Arasan includes sources and makefiles
for building the chess program for both 16- and 32-bit Windows, and
also source and executables for the following 32-bit console programs:

makebook - builds binary opening book files from book.txt
makeeco  - builds ecodata.h from from "eco" text file
testsrc  - test program for Arasan search engine
arasanx  - version of Arasan that can use Winboard as a front end.

Following is a sketch of the Arasan source directory tree:

arasan
  3.2
    src     - source code
       res  - resource files, bitmaps, icons
    book    - text files for opening book and ECO recognizer
    help    - help file source
    doc     - documentation
    tests   - test files and documentation
    install - install script
    win32   - makefiles, objects, and executables for win32
       WinRel - release objects and binaries
       WinDebug - debug objects and binaries
       ToolsRel - release objects and binaries for tools
       ToolsDbg - debug object and binaries for tools

The project file "arasan32.mdp" in the win32 subdirectory is used
to build the chess program itself.  The release version object and
binaries are placed in the "WinRel" directory under win32, while the
debug objects and binaries are put into "WinDebug".  There is also a
"tools32.mak" makefile for building the support tools.  Release objects
and binaries for these tools go into the "ToolsRel" directory, while
debug objects and binaries go into "ToolsDbg". 

Compiled versions of the tool programs are supplied in the
win32\ToolsRel directory. 

Opening book

Arasan stores the opening book in a binary file (BOOK.BIN). 

Since BOOK.BIN is supplied with the Arasan program distribution, you do
not need to build this file in order to build Arasan.  However, if you
want to modify the contents of the opening book, you will need to edit
the ASCII source for the openings and rebuild BOOK.BIN.  Following is
information on how to do this. 

The ASCII source for the opening book is contained in the file
BOOK.TXT, which is in the book directory.  Moves are listed one or
more per line.  Most are in standard algebraic notation, but in some
cases "Informant-style" notation is used (e.g. knight takes bishop
might be written Nb2, not Nxb2).  The parser recognizes both forms.

A move may optionally be followed by a number from 0 to 9.  The number,
if given, is the "weight" assigned to the move.  A weight of 0 means
that the computer will never play the move, but will respond to it if it
is played by its opponent.  The higher the weight, the more often the
computer will choose the move compared to the other alternatives in the
book.  By default, if no weight is specified, a weight of 5 is assigned. 

If the same position occurs later in the book, any weight given for
it is ignored.  Only the first weight given is significant.

The supplied book uses weights rather sparingly.  In general, the
computer has been steered away from gambits, and away from openings it
doesn't play well.  It is also biased towards playing the main line of
an opening as opposed to less common variants.  Note: I am not a strong
player, and so the opening book is probably far from optimal. 

Some special symbols are allowed in the opening book.  Any line
beginning with ";" is treated as a comment and ignored.  An "s" in the
first column followed by a number sets the opening "style" (see
bookdefs.h for the style definitions).  An "m" in the first column means
that the present position should be remembered.  An "r" in the first
column restores the position to where it was when the last "m" was
encountered.  This allows easy entry of variant lines from the same
starting position.  Only one remembered position can be stored and
retrieved, however: e.g. if you specify "m" twice, the first position
stored is discarded. 

After changing the book file, just type:

makebook -n 4 book.txt

from the command line to rebuild the data file (book.bin.  The "-n 4"
specifies 8 "pages" (data structures) in the opening book, enough to
hold about 80,000 moves.

See makebook.cpp for some documentation about the data layout within
the opening book.

A small separate book file (STYLES.BIN) is used for the "style" feature
in Arasan 3.0.  If an opening style other than "Balanced" is specified
in the Openings preferences page, then the styles.bin book will be
searched before the regular opening book.  Only those moves in
styles.bin that match the preferred style of opening will be selected.
If no such move is found, the regular opening book is searched. 

The opening moves for the various styles are stored in STYLES.TXT.
The following command line is used to rebuild the style book:

makebook -h 101 -n 1 -p 3000 -o styles.bin styles.txt


ECO Recognizer

Arasan can produce an ECO (Encylopedia of Chess Openings) code for a
given game.  As with the opening book, the mapping of chess positions to
ECO codes is contained in a text file.  The file is called "eco" and is
in the "misc" directory.  It contains a series of lines, each starting
with an ECO code, followed by a series of chess moves, and ending with a
quoted string that contains the English name of the opening. 

The "makeeco" program reads the "eco" data file and outputs to stdout
a header file that is then compiled into Arasan.  The header file is
called "ecodata.h" and contains a single large C data structure.  

Because Visual C++ makefiles don't handle generated source files like
this one, you need to run "makeeco" manually whenever you change the
"eco" data file.  To do this, CD to the src directory, and type:

..\win32\makeeco ..\data\eco >ecodata.h

Note: the ECO recognizer is pretty crude right now, because only the
main ECO lines are stored in the data file, not sublines like "ECO
C18/3".  Therefore transpositions that wind up in an ECO subline like
C18/3 but skip the position that is stored for C18 will not be
recognized correctly.  There is no general solution for this problem,
since the ECO classification scheme is ambiguous in some cases, but
recognition could be improved by expanding the number of positions in
the eco file.  If the number becomes large enough, however, the
current method of building a data structure and compiling it into
Arasan might have to be changed.


Testing support

Arasan includes several features to aid debugging.  If you compile the
source for debugging (with -D_DEBUG), checks are inserted for accessing
arrays past their boundaries, as well as some other sanity checks.  If
any of these checks fail, an error box will be displayed with the
assertion that failed. Another compile-time debugging option is
-DDEBUG_ATTACKS, which will insert test code to check that the attack
information for the board is updated correctly when a move is made. 

For debugging purposes, it is also possible to build a console program
that contains the Arasan search engine, but no user interface.  This
executable is called "TESTSRC" and can be built from the "tools"
makefile. 

TESTSRC takes a command line that consists of one or more optional
switches followed by a filename.  The allowable switches are:

-p <number> - performs a fixed-ply search to the indicated depth.
-t <number> - searches for the given number of seconds.
-H <number> - hash table size (number of nodes)
-v          - "verbose", print extra information, not just the result.
-n<0|1|2>   - depth reduction for null moves (default: 2)
-k<0|1|2>   - number of killer moves per ply (default: 2)
-c<+|->     - check extensions on or off (default: on)
-f<+|->     - forced move extensions on or off (default: on)
-pp<+|->    - pawn push extensions on or off (default: on)
-h<+|->     - history heuristic on or off (default: on)

Note: the -p and -t switches are mutually exclusive, i.e. they may
not be specified together.  Switches like -c have two settings.
Specifying -c- will turn off check extensions, -c+ will turn them
on.  Extensions, killers, etc. are explained in more detail later on.

The filename specified contains one or more board positions to
be analyzed.  The position info is in stored in FEN (Forsythe-Edwards
notation).  Each line in the file begins with one of the following
commands:

"svfe" - which indicates a position follows
"srch" followed by one or more moves - correct or recommended moves
"noop" - a comment line
"echo" - a line to echo to stdout.

The TESTSRC program will read each position from the file, analyze
it, and report at the end the number of correct answers, the total
number of nodes searched, and the total time elapased.

If the search module is compiled with -D_TRACE, TESTSRC will print
out copious information about the search process when it is run.  See
search.cpp to see what information is output and where it comes from.

Because TESTSRC is a console program, it can easily be run from a
batch file to execute a series of tests.  The following test suites
are provided with the source code (see the TESTS directory):

1. EASY.CI contains 24 fairly simple tactical problems.  Arasan
should solve all these problems with a fixed depth of 4 plies (-p 4).

2. WAC.CI contains the 300 problems from Reinfeld's "Win At Chess"
book.  These are mostly easy tactical problems.

3. WCSAC.CI contains problems from Reinfeld's 1001 Winning Chess
Sacrifices and Combinations.  These are tactical problems similar in
difficulty to the "Win At Chess" series.

4. The file BK.CI contain the Bratko-Kopec series of tests.  It is
standard procedure to allow the program 2 minutes for each test.
Some of these problems are quite difficult.

5. The file ECE3100.CI contains the first 100 problems from
Encyclopedia of Chess Endgames, volume 3.  These are rook endgames.

6. Another endgame test suite is FINE.CI, containing 48 king and
pawn endgame problems from Reuben Fine's Basic Chess Endings.

7. ECM.CI contains test positions from the Encyclopedia of Chess
Middlegames.  These are difficult middlegame problems.

8. BT2630.CI is a set of 30 rather difficult problems.  This is
used to determine an approximate rating for the program.  Standard
procedure is to allow 15 minutes for each problem.  Add the time
needed to find the correct answer (900 for problems that are not
solved), divide by 30, and subtract from 2630.  Based on this test,
Arasan 3.2 has a rating of 2045 on a Pentium 133.

9. LAPUCE2.CI is a set of 35 tests from the French chess magazine
La Puce Echiqueenne.  This is another test that purports to estimate
a program's rating.  Standard procedure is to allow 10 minutes for
each problem.  See LAPUCE2.DOC for the scoring procedure.  Arasan 3.2
has a rating of 2000 based on this test, on a Pentium 133.

The RESULTS file in the TESTS subdirectory summarizes Arasan's
performance on these test suites.  Note: these results were obtained
from the TESTSRC program.

The "arasanx" program can be used to run Arasan as a Winboard client.
Winboard is a graphical display program that connects to a chess engine
executable.  You can get Winboard from caissa.onenet.net (directory
/pub/chess/Win3) and many other locations.  I use arasanx mostly to make
Arasan play games against Crafty or Gnuchess; you can do this by using
the -firstChessProgram and -secondChessProgram switches to WinBoard,
like this:

   winboard -firstChessProgram "d:\\arasan\arasanx.exe" 
    -secondChessProgram "d:\\crafty\\crafty.exe -xboard"

Then select "Two Machines" in the Mode menu.  Eventually I hope to
enhance arasanx so that it can function as an ICS (Internet Chess
Server) client as well.


Algorithms and data structures

1. The chess board

Following is some information about the algorithms and data
structures used by Arasan.  If you are new to computer chess
programming, I suggest first reading a general work on the
subject such as Frey (1983) or Marsland and Schaeffer (1990).

The chess board in Arasan is represented by an array of 64 squares,
laid out so that square a8 has the value 0 and square h1 has the
value 63.

Each square contains 0 if it is empty, or a piece identifier if it is
occupied.  Black pieces have identifier values between 1 and 6, while
White pieces have values between 9 and 15.   A special value (127) is
used to represent a square that is uninitialized or invalid. 

The Board class also maintains a parallel board representation called
"PiecePos" consisting of two arrays of 16 entries each.  These contain
lists of the squares occupied by pieces of each side.  Any array
entry unoccupied by a piece is set to 127.

Several other pieces of information are stored in the Board class and
are updated for each move.  The KingPos array holds the location of
each side's king.  The PFileCount array holds a count of the number
of pawns on each file, for each side, and the RFileCount array holds
a similar value for rooks.  The pawn_bits data member contains a 64-
bit bitmap with bits set for each square that contains a pawn of the
appropriate color.  This is used for detecting passed, isolated, and
backward pawns.

The EnPassantSq array holds the square position, for each side, on
which an en passant capture is possible (obviously, only the side to
move can have a possible en passant capture, but we maintain two
values for programming convenience).  The CastleStatus array holds an
enum for each side indicating whether castling has occurred.  Also,
if the king or a rook has been moved, making castling on one side or
another impossible, CastleStatus is set to an appropriate value.

Each board position also has a hash code associated with it.  The
hash code is 32 bits and is computed by fetching, for each piece and
square combination, a unique 32-bit code from a table of random
numbers, and computing the exclusive or of these codes.  The
low-order bit of the hash code is then set to identify whether White
or Black is to move.  Castling status and en passant status are not
folded into the hash code, but are stored in a separate field in a
hash table entry - they must match the current board in order
for a position to be retrieved from the table.

Finally, the board position includes an array, for each side, of type
Attacks.  This contains an integer for each square indicating which
pieces and of what kinds attack the square.  This information is
incrementally updated (by the Attacks class) when a move is made or
unmade.  Attacks does not store information about "stacked"
attackers, which may make some calculations involving this
information inaccurate.

An earlier chess program I wrote re-calculated complete attack
information for each position that was evaluated, but it wound up
spending a large fraction of its time in the attack calculation
procedure.  Incrementally updating the attack information is
relatively cheap and probably faster.

2. Moves

There are three move classes used in Arasan.  "Move" maintains only
the minimal information need to unambiguously specify a move: start
square, destination square, and promotion value.  "ExtendedMove"
contains also the piece being moved, the piece being captured (if
any), and the type of move (normal, castling, en passant, etc).
Finally, "ReversibleMove" contains in addition the castling and en
passant status of the board before the move was made.  Since this
information is needed for restoring the board position, only a
ReversibleMove can be "undone".

Note: it is generally faster to save the complete board state, make a
move and then copy the board state back, than to "undo" a move, putting
back only the parts that the move changed.  Arasan used to have an
"UndoMove" function, but it is no longer present.

3. Move Generator

The move generation logic is mostly contained in the classes Bearing,
Move_Generator and Move_Ordering.  Bearing contains static functions
to compute squares to which a piece can move.  Except for pawn moves,
and for castling, move generation is done by table lookup.  Each
class of piece has an associated table.  Each table is indexed by
square number and side to move, and contains a list of squares to
which the piece could move (these tables are in beardata.h).
Additional checks are made to see that the destination square doesn't
contain a piece of the same color.  However, moves into check are
possibly included.

The Move_Generation class uses functions from Bearing to generate all
moves for a given side.  Moves into check are included, unless the
side to move is in check.  In that case, a special function
(Check_Evasions) is called that strictly checks moves for legality.
It is very important to know whether any legal moves are possible
when in check: if there are none, the side to move is checkmated.
Also, some search extensions depend on the existence of a forced move
(one single legal move).

Move_Generation also calls the Move_Ordering class to re-order the
moves.  At ply 0, some rather elaborate criteria are used for move
ordering: this includes a computation of each moves' positional
score, and also (for captures), a call to function attack_estimate,
which uses the attack information for the destination square to
estimate the gain from a capture.  

At higher plies, a somewhat different and faster algorithm is used.  The
principal variation (best move from a previous search of this node) is
always put first.  Then capture moves that appear to gain material are
tried, along with pawn promotions.  Then the two "killer" moves (moves
which have recently caused beta cutoff) are tried.  Finally, the
remaining moves are sorted in the order of their "history" values. 

4. Searching

Arasan uses an alpha-beta search algorithm with a variety of search
extensions.  The search class is the largest single module in the
program, and is necessarily rather complicated, but I have tried to
structure it and comment it so that it is understandable.  I will
assume that the reader knows the basics of the alpha-beta algorithm,
and will concentrate on describing this implementation of it.  Note:
the 16-bit version of Arasan has a significantly different search
engine.  This text describes the 32-bit version.

In general, the search routine tries to terminate a search tree, or
some portion of one, as soon as possible, and will defer as much work
as possible until it is certain that no earlier and quicker
termination can be done.  The techniques for doing this are mostly
well-known and there is nothing very original about the search
algorithms used by Arasan.  However, as with most chess programs,
there is a fine balance between terminating a search too soon and
extending it into unprofitable and very unlikely lines of play.  The
precise nature of this balance depends not only on the search
algorithms used, but also the relative efficiency of operations such
as move generation, position evaluation and move ordering.  Each
program therefore strikes this balance in a somewhat different way.

The entry point for a search is a routine called find_best_move.  This
function does some initialization, and then calls move_search, which
implements the alpha-beta search algorithm.  The search proceeds one
ply (half move, i.e. move by one side) at a time.  That is, first a
one-ply search is done, then a two-ply search, then three, etc. until
either the maximum ply limit has been reached or the time control has
been exceeded.  Each search uses the results of the preceeding search.
The variable "iteration_depth" holds the current nominal ply depth for
the search.  However, the presence of search extensions means that
some nodes may be searched to a greater depth than this. 

The first step in move_search is to check if the current board position
is drawn, due to insufficient material or to a 3-fold repetition of
moves.  Arasan does not currently check for draws due to the 50-move
rule or variants of it. 

If the position is drawn, move_search calls the function draw_score,
which penalizes the program for allowing a draw when it is ahead in
material or has a superior position.  There is also a penalty for
making a draw early in the game.

Arasan will also terminate the search immediately if the absolute
maximum ply depth (currently 40) is reached.  This is quite unlikely.

If no draw is present and the maximum depth hasn't been reached, the
next step is to look in the hash table (further described in the next
section), in order to see if an identical position has been visited
before.  This may happen due to a transposition of moves that lead to
the same position, or because a previous search to a shallower depth
visited the same node.  If a hash table entry is found and if it
contains a valid value (i.e. one that did not cause cutoff), then that
value is returned immediately and no further searching from that node
occurs.  In other cases, the hash table may not contain an exact value,
but may hold an upper or lower bound that can be used to narrow the
alpha-beta window. 

If the hash table lookup didn't produce an exact value or narrow the
bounds enough to cause cutoff, then we try a further trick to get a fast
termination of the search.  The side to move is changed without altering
the board position and the opposing side is then allowed to move.  Of
course, this could not occur in a game - a player is not allowed to
"pass," but must move.  However, the theory is that if the null move
causes cutoff, then the side to move must have a good position, since in
effect giving the opponent a free move still produces a high value for
the side to move.  In this case, beta cutoff is allowed to occur and no
more searching is done from this node.

Starting in Arasan 2.0, null move pruning is applied in subtrees that
are themselves part of a null move search, provided that two null moves
are not tried in a row.  This is known as the "deep null" algorithm. See
Donninger's article in ICCA for more information on this algorithm. 

If the null move doesn't cause cutoff, then we must actually do some
searching from the current node.  Before doing this, we check to see
if the current node should be searched to a greater depth than normal.
There are three cases in which this occurs:

a. If the side to move is in check, the search is extended an extra ply.

b. Forced moves (moves with only one possible reply) cause
the search to be extended one ply.

c. Pushing a pawn to the 7th rank causes the search to be extended one
ply, on the theory that this pawn may soon promote.

Each type of extension can be turned on or off via the "Advanced"
preferences dialog.

The first move searched is called the "principal variation" move.  In
the case of an initial search (e.g. a one-ply search), the principal
variation move is just the first move returned by the move generator.
Otherwise, at ply 0, it is the highest-scoring move from the previous
search iteration.  This is obtained by sorting the 0-ply moves from the
last iteration, all of which were stored along with their scores.  At
deeper plies, the hash table is queried and if a best move has been
stored for the position, that move is tried first and is considered the
principal variation. 

In cases where there is no hash move, we do a shallow search to obtain
a suitable move to try first.  This is called "internal iterative
deepening" and has been used in Hitech (see Ebeling's book) and also
Bob Hyatt's program Crafty. 

Now we should have an initial move to try.  We make the move, then query
the attack info for the board to see if the side to move is in check
(remember, the move generator typically does not exclude moves into
check).  If a move into check is found, the special value Illegal is
returned and the next move is tried.  If the move passes the legality
check, then move_search is called again (i.e., it is recursive). 

Each recursive call to move_search decrements the "depth" parameter by
one.  When it reaches zero, we enter the quiescence search.  The
difference between the regular and the quiescence search is that the
latter will call the function "quiesce" instead of move_search.
"quiesce" will only generate and search capture moves that appear to
gain material, promotions of pawns, and moves that escape from a
check.  

As the name implies, the goal of the quiescence search is to reach a
relatively "quiet" position that can be more or less accurately
evaluated.  The quiescence search terminates when no more moves of an
appropriate type are available.  The search may also terminate early
if the side to move is not in check, and the current evaluation of the
position is enough to cause cutoff.  The theory here is that the side
to move can choose to not capture any further.  If the current
evaluation is good enough to cause cutoff, there is no need to try
captures and promotions to get a better score. 

The principal variation phase of the search is over when we have found
a legal move and searched its descendants (including quiesence nodes)
so that we have a value for it.  It is possible that this value will
be greater than beta, which means that we have set the initial search
window wrong and must repeat the search with a different window.

Assuming the principal variation move does not cause cutoff or mate,
then move_search proceeds to search the remainder of the moves.  These
moves are searched with a zero-width alpha-beta window (i.e. beta is set
to alpha+1).  All such searches will cause a cutoff.  If the value
returned by the search is between alpha and the original beta, then the
search is repeated with a wider search window to determine the correct
score.  It is generally faster to get a fast cutoff and then re-search
with a wider (but not infinite) window than to do a single search with
unlimited bounds. 

Note that since the principal variation move is usually obtained from
the hash table or the ply0moves array, it may be the case that the
move generator has never had to be called during the principal
variation search.  If so, we call it before doing the non-p.v. moves.
An earlier version of Arasan tried to optimize things further by only
generating part of the moves at a time.  That way, if cutoff
occurred, the remainder of the move generation could be skipped.
However, there was a cost to this in terms of complexity and it did
not seem to help search speed much.

The final part of move_search checks to see if checkmate or stalemate
occurred, and updates the hash table.

When the top-level invocation of move_search terminates, it returns
to find_best_move, which determines the time used, and updates the
"Statistics" structure with the time and other information about the
search.

5. The hash table

The search routine uses a hash table for storing the results of
evaluating previously visited positions.  This table is implemented
in the "Hash" class, which is based on the MFC class CPtrList.  The
hash table is basically an array of lists.  Each list contains a
series of nodes, each of which contains some data (in the case of the
search engine, a class of type Position_Info) and a pointer to the
next node.  Each list holds entries that hash, modulo the hash table
size, to the same value.  Each node contains the whole hash code, so
that finding a given node to match a given hash code consists of
indexing into the hash table, then following the list until the hash
codes match.

Besides the hash code, each hash entry also contains the score for
the node, a set of flags indicating whether the value is exact, an
upper bound or a lower bound, the depth of search used to evaluate
the node, a word holding the castling status and en passant square,
and the best move for the position.

Currently the hash table is used only during the regular seach, not
in the quiescence search.  The hash table is cleared after each search. 

Under Windows, the size of the hash table is configured at runtime based
on the amount of memory available.  The user can also override this
calculation and specify a different size.  The "testsrc" console program
uses a fixed-size hash table: the default size is 65536 entries, but
this can overridden with a command-line switch.

Memory allocation and deallocation for the hash table can be quite
expensive, especially under Windows.  To minimize this, operators new
and delete are overloaded for the Position_Info class.  These
operators use a simple memory allocation scheme that obtains memory
from the OS in large chunks and does suballocation out of the chunks
(class Pool implements this).  Memory freed via "delete" goes into a
free list and is immediately available for allocation again via
"new".  Memory is not actually freed until the "freeAll" method is
called, which occurs only when the hash table is cleared.  Then the
large memory chunks are returned to the OS.

6. Position Scoring

There are five main components to the positional score used by Arasan:

a. Center control
b. Development
c. Castling
d. Pawn structure
e. King safety

The positional score is typically within the range of plus or minus
the value of a pawn (64), but can be greater in some circumstances.

When in the endgame (determined by the amount of material on the
board) simplified and/or different scoring parameters are used.
Also, special scoring code is used for "mopping up" positions, in
which one side has a large material advantage.  Chess 4.5 from
Northwestern University used a similar scheme.

Center control is mostly calculated by table lookup.  For sliding
pieces, a check is made to be sure that the piece has an unobstructed
line of movement to the center of the board.  This component of the
score is not used in the endgame.

The development score encourages the program to move its pieces from
the back rank, but discourages premature development of the queen.  A
measure of piece mobility is also calculated for bishops and rooks.
Bonuses are awarded for a rook on the 7th rank, and also for a rook
on an open or half-open file, and for doubled rooks.

In the endgame, the development score encourages the king to move
towards the center or opposite side of the board, and to stay near
pawns.  A bonus is also awarded for having the opposition.  This code
is not very effective in producing good play, but it is better than
nothing.  Special-case code is included for KPK and KNBK endgames,
which enables the program to play these fairly well.

When "mopping up", the development score gives a bonus for
restricting the opposing king's mobility and for driving the opposing
king to an edge or corner of the board. 

The castling score penalizes the program for being unable to castle,
either temporarily (because a square traversed by castling is under
attack) or permanently (because the king or rook has made another
move).

The pawn structure score penalizes isolated, backward, and doubled
pawns, and gives a bonus for passed pawns.  If a passed pawn exists,
its value depends on its rank and also on whether squares ahead of it
are occupied or controlled by the opposing side.

The king safety score evaluates the extent to which the king is
protected by pawns, and also the extent to which opposing pieces
attack squares near the king.  It is pretty inexact, but does at
least alert the side to move when the king is in serious trouble.


Contacting the Author

I have been working on computer chess programming for over seven
years, and this is the second complete chess program I have written.
It is still very much imperfect - but I have decided to release it in
its present form, both so that others can enjoy playing with it and
so that programmers can study it, learn from it, and maybe improve
it.  I don't guarantee any support for this program.  However, if you
do find bugs in it, or discover a way to improve it, I would like to
hear from you.  I can be reached via email at jdart@best.com.


References

Donninger, Ch. 1993. "Null Move and Deep Search" ICCA Journal,
v. 16 no. 3.

Ebeling, Carl. (1987). All The Right Moves: A VLSI Architecture for Chess.
MIT Press.

Frey, Peter W. (ed.) (1983). Chess Skill in Man and Machine.
New York: Springer-Verlag.

Marsand, T. Anthony and Schaeffer, Jonathan (1990).  Computers,
Chess and Cognition. New York: Springer-Verlag.


