~ubuntu-branches/ubuntu/hardy/dbacl/hardy

« back to all changes in this revision

Viewing changes to doc/chess/dce.sh

  • Committer: Bazaar Package Importer
  • Author(s): Zak B. Elep
  • Date: 2006-03-26 22:35:35 UTC
  • mto: (2.1.1 etch) (1.1.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20060326223535-icwiulpkzesds4mq
ImportĀ upstreamĀ versionĀ 1.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/bash
 
2
# This script is a simple chess engine for dbacl and XBoard.
 
3
# It is based on the essay 
 
4
#
 
5
# "Can spam filters play chess?" (c) 2005 Laird A. Breyer
 
6
# http://www.lbreyer.com/spam_chess.html
 
7
 
8
# The essay explains the construction of this engine by
 
9
# successive modifications of the dce-basic.sh script.
 
10
#
 
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.
 
16
#
 
17
# Revision history:
 
18
 
19
# 28/06/2005 (Laird Breyer) Initial release.
 
20
#
 
21
 
 
22
DBACL=./dbacl/src/dbacl
 
23
SAN=./SAN/SAN_SRC/san
 
24
TMP=.
 
25
DCE=dce.$$
 
26
 
 
27
SANOK="no"
 
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"
 
35
 
 
36
RANPLAY="no"
 
37
SIDE="black"
 
38
MOVENOW="no"
 
39
FORCEMODE="no"
 
40
CATFILE="./BlackWinDraw"
 
41
 
 
42
trap "" SIGTERM
 
43
trap "" SIGINT
 
44
 
 
45
function exec_san() {
 
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"
 
51
                return 1
 
52
        else 
 
53
                mv $PGN.new $PGN
 
54
        fi
 
55
        return 0
 
56
}
 
57
 
 
58
function do_reset() {
 
59
        rm -f $PGN
 
60
        touch $PGN
 
61
        exec_san ""
 
62
 
 
63
        SIDE="black"
 
64
        FORCEMODE="no"
 
65
        MOVENOW="no"
 
66
}
 
67
 
 
68
function do_move() {
 
69
        if [ "$SANOK" != "yes" ]; then
 
70
                echo "Illegal move (you must use SAN): $1"
 
71
                echo "Error (cannot play): $1"
 
72
        fi
 
73
        if exec_san "$1"; then
 
74
                MOVENOW="yes"
 
75
        fi
 
76
}
 
77
 
 
78
function echo_gameline() {
 
79
        cat "$PGN" \
 
80
        | sed -e 's/\r//g' \
 
81
        | sed -e :a -e '$!N;s/\n\([a-hKQNBRO0-9]\)/ \1/;ta' -e 'P;D' \
 
82
        | sed -e 's/^ *//' \
 
83
        | grep '^1\.' \
 
84
        | sed 's/[0-9]*\.[ ]*//g' \
 
85
        | sed 's/ \*.*$//'
 
86
}
 
87
 
 
88
function echo_completions() {
 
89
        # legal moves are in $SANOUT
 
90
        cat "$SANOUT" \
 
91
        | grep '.* : 1$' \
 
92
        | cut -f 1 -d ' ' \
 
93
        | while read move; do
 
94
                echo "`cat $GAMELINE` $move"
 
95
        done
 
96
}
 
97
 
 
98
function randomizer() {
 
99
        # assume stdin is sorted and $2 is the score
 
100
        awk '
 
101
{
 
102
  if( cf == 0 ) {
 
103
    cf = $2;
 
104
  }
 
105
  score[NR] = $2 - cf;
 
106
  line[NR] = $0;
 
107
}
 
108
 
 
109
END{
 
110
  srand();
 
111
  while(1) {
 
112
    x = int(rand() * NR) + 1;
 
113
    t = -log(rand());
 
114
    if( log(2) * score[x] < t ) {
 
115
      print line[x];
 
116
      break;
 
117
    }
 
118
  }
 
119
}
 
120
'
 
121
}
 
122
 
 
123
function echo_best_move() {
 
124
        # assume $1 is sorted already
 
125
        if [ "$RANPLAY" = "yes" ]; then
 
126
                cat $1 \
 
127
                | randomizer \
 
128
                | sed -e 's/^.* //'
 
129
        else 
 
130
                cat "$1" \
 
131
                | head -1 \
 
132
                | sed -e 's/^.* //'
 
133
        fi
 
134
}
 
135
 
 
136
function combine_halfmoves() {
 
137
        sed -e 's/$/ Z/' -e 's/ \([^ ]* *[^ ]\)/_\1/g' -e 's/[ ]*Z$//'
 
138
}
 
139
 
 
140
function split_fullmove() {
 
141
        sed -e 's/.*_//'
 
142
}
 
143
 
 
144
function get_captures() {
 
145
        cat "$SCORES" \
 
146
        | grep '^.* [^ ]*x[^ _]*$' \
 
147
        > "$CAPTURES"
 
148
 
 
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"
 
159
 
 
160
        N=`cat $CAPTURES| wc -l`
 
161
 
 
162
        if [ "$N" = "0" -o "$N" = "1" ]; then
 
163
                # don't recommend capture
 
164
                return 1
 
165
        fi
 
166
        # tell engine to make a capturing move
 
167
        return 0
 
168
}
 
169
 
 
170
function do_engine_move() {
 
171
        if exec_san "enum 1"; then
 
172
 
 
173
                echo_gameline > "$GAMELINE"
 
174
 
 
175
                # make all completions and let dbacl decide
 
176
                echo_completions \
 
177
                | combine_halfmoves \
 
178
                | "$DBACL" -n -c "$CATFILE" -f 1 \
 
179
                | sort -k 2 -n \
 
180
                > "$SCORES"
 
181
                
 
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?}"
 
186
                        return 0
 
187
                else
 
188
                        # pick best scoring move
 
189
                        echo_best_move "$SCORES" \
 
190
                        | split_fullmove \
 
191
                        > "$ENGINEMOVE"
 
192
        
 
193
                        if get_captures; then
 
194
                                echo_best_move "$CAPTURES" \
 
195
                                | split_fullmove \
 
196
                                > "$ENGINEMOVE"
 
197
                        fi
 
198
 
 
199
                        if exec_san "`cat $ENGINEMOVE`"; then
 
200
                                echo "move `cat $ENGINEMOVE`"
 
201
                                return 0
 
202
                        fi
 
203
                fi
 
204
 
 
205
        fi
 
206
        return 1
 
207
}
 
208
 
 
209
function get_side_to_play() {
 
210
        N=`echo_gameline | wc -w`
 
211
        if [ "`expr $N % 2`" = "0" ]; then
 
212
                SIDE="white"
 
213
        else
 
214
                SIDE="black"
 
215
        fi
 
216
}
 
217
 
 
218
while read cmd; do
 
219
        case "$cmd" in
 
220
        xboard)
 
221
                echo "feature san=1 done=1"
 
222
                ;;
 
223
        "accepted san")
 
224
                SANOK="yes"             
 
225
                ;;
 
226
        random)
 
227
                RANPLAY="yes"
 
228
                ;;
 
229
        quit)
 
230
                exit 0
 
231
                ;;
 
232
        new)
 
233
                do_reset
 
234
                ;;
 
235
        variant*)
 
236
                echo "Error (only standard chess please): $cmd"
 
237
                ;;
 
238
        force)
 
239
                FORCEMODE="yes"
 
240
                ;;
 
241
        white)
 
242
                SIDE="black"
 
243
                ;;
 
244
        black)
 
245
                SIDE="white"
 
246
                ;;
 
247
        go)
 
248
                get_side_to_play
 
249
                FORCEMODE="no"
 
250
                MOVENOW="yes"
 
251
                ;;
 
252
        [a-h][x1-8]*)
 
253
                do_move "$cmd"
 
254
                ;;
 
255
        [KQBNRP][xa-h]*)
 
256
                do_move "$cmd"
 
257
                ;;
 
258
        O-O*)
 
259
                do_move "$cmd"
 
260
                ;;
 
261
        analyze)
 
262
                echo "Error (unknown command): $cmd"
 
263
                ;;
 
264
        *) 
 
265
                # ignore other commands
 
266
                echo "Error (command not implemented): $cmd"
 
267
                ;;
 
268
        esac
 
269
        if [ "${FORCEMODE}${MOVENOW}" = "noyes" ]; then
 
270
                if do_engine_move; then
 
271
                        MOVENOW="no"
 
272
                else
 
273
                        echo "Error (engine blew up): kaboom"
 
274
                        exit 1
 
275
                fi
 
276
        fi
 
277
done
 
278
 
 
279
# don't forget to clean up
 
280
rm -f $DCE.current.*
 
 
b'\\ No newline at end of file'