2
# This script is a simple chess engine for dbacl and XBoard.
3
# It is based on the essay
5
# "Can spam filters play chess?" (c) 2005 Laird A. Breyer
6
# http://www.lbreyer.com/spam_chess.html
8
# The essay explains the construction of this engine by
9
# successive modifications of the dce-basic.sh script.
11
# THE dce-*.sh SCRIPTS ARE INCOMPLETE ENGINES AND INTENDED
12
# ONLY FOR ILLUSTRATION OF POINTS RAISED IN THE ESSAY.
13
# IF YOU WANT TO TRY OUT YOUR OWN MODIFICATIONS OF THE
14
# CHESS ENGINE, YOU SHOULD MAKE A COPY OF THE FINAL (dce.sh)
15
# FILE AND CHANGE THAT COPY.
19
# 28/06/2005 (Laird Breyer) Initial release.
22
DBACL=./dbacl/src/dbacl
28
PGN="$TMP/$DCE.current.pgn"
29
GAMELINE="$TMP/$DCE.current.gameline"
30
SCORES="$TMP/$DCE.current.scores"
31
CAPTURES="$SCORES.cap"
32
ENGINEMOVE="$TMP/$DCE.current.emove"
33
SANOUT="$TMP/$DCE.current.stdout"
34
SANERR="$TMP/$DCE.current.stderr"
40
CATFILE="./BlackWinDraw"
46
rm -rf $PGN.new $SANOUT $SANERR
47
echo -ne "svop namd nabd napr\nlfer $PGN\n$1\nsfer $PGN.new" \
48
| "$SAN" > "$SANOUT" 2> "$SANERR"
49
if grep Error "$SANOUT" > /dev/null; then
50
echo "Error (illegal move): $cmd"
69
if [ "$SANOK" != "yes" ]; then
70
echo "Illegal move (you must use SAN): $1"
71
echo "Error (cannot play): $1"
73
if exec_san "$1"; then
78
function echo_gameline() {
81
| sed -e :a -e '$!N;s/\n\([a-hKQNBRO0-9]\)/ \1/;ta' -e 'P;D' \
84
| sed 's/[0-9]*\.[ ]*//g' \
88
function echo_completions() {
89
# legal moves are in $SANOUT
94
echo "`cat $GAMELINE` $move"
98
function randomizer() {
99
# assume stdin is sorted and $2 is the score
112
x = int(rand() * NR) + 1;
114
if( log(2) * score[x] < t ) {
123
function echo_best_move() {
124
# assume $1 is sorted already
125
if [ "$RANPLAY" = "yes" ]; then
136
function combine_halfmoves() {
137
sed -e 's/$/ Z/' -e 's/ \([^ ]* *[^ ]\)/_\1/g' -e 's/[ ]*Z$//'
140
function split_fullmove() {
144
function get_captures() {
146
| grep '^.* [^ ]*x[^ _]*$' \
149
# we rearrange the captures in order of least important piece to
150
# most important piece
151
grep -v '[NBRQK][^_ ]*$' "$CAPTURES" > "$CAPTURES.new"
152
grep 'N[^_ ]*$' "$CAPTURES" >> "$CAPTURES.new"
153
grep 'B[^_ ]*$' "$CAPTURES" >> "$CAPTURES.new"
154
grep 'R[^_ ]*$' "$CAPTURES" >> "$CAPTURES.new"
155
grep 'Q[^_ ]*$' "$CAPTURES" >> "$CAPTURES.new"
156
# king is too valuable to force captures
157
# grep 'K[^_ ]*$' "$CAPTURES" >> "$CAPTURES.new"
158
mv "$CAPTURES.new" "$CAPTURES"
160
N=`cat $CAPTURES| wc -l`
162
if [ "$N" = "0" -o "$N" = "1" ]; then
163
# don't recommend capture
166
# tell engine to make a capturing move
170
function do_engine_move() {
171
if exec_san "enum 1"; then
173
echo_gameline > "$GAMELINE"
175
# make all completions and let dbacl decide
177
| combine_halfmoves \
178
| "$DBACL" -n -c "$CATFILE" -f 1 \
182
if [ "`cat $SCORES| wc -l`" = "0" ]; then
183
# no moves left, game over!
184
# the gameline contains the result
185
echo "`cat $GAMELINE | sed 's/^.* //'` {Play again?}"
188
# pick best scoring move
189
echo_best_move "$SCORES" \
193
if get_captures; then
194
echo_best_move "$CAPTURES" \
199
if exec_san "`cat $ENGINEMOVE`"; then
200
echo "move `cat $ENGINEMOVE`"
209
function get_side_to_play() {
210
N=`echo_gameline | wc -w`
211
if [ "`expr $N % 2`" = "0" ]; then
221
echo "feature san=1 done=1"
236
echo "Error (only standard chess please): $cmd"
262
echo "Error (unknown command): $cmd"
265
# ignore other commands
266
echo "Error (command not implemented): $cmd"
269
if [ "${FORCEMODE}${MOVENOW}" = "noyes" ]; then
270
if do_engine_move; then
273
echo "Error (engine blew up): kaboom"
279
# don't forget to clean up
b'\\ No newline at end of file'