1 /* swap.c
2
3 GNU Chess frontend
4
5 Copyright (C) 2001-2011 Free Software Foundation, Inc.
6
7 GNU Chess is based on the two research programs
8 Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23 Contact Info:
24 bug-gnu-chess@gnu.org
25 cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
26 */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include "common.h"
31
32 static const int xray[7] = { 0, 1, 0, 1, 1, 1, 0 };
33
SwapOff(int move)34 int SwapOff (int move)
35 /****************************************************************************
36 *
37 * A Static Exchange Evaluator (or SEE for short).
38 * First determine the target square. Create a bitboard of all squares
39 * attacking the target square for both sides. Using these 2 bitboards,
40 * we take turn making captures from smallest piece to largest piece.
41 * When a sliding piece makes a capture, we check behind it to see if
42 * another attacker piece has been exposed. If so, add this to the bitboard
43 * as well. When performing the "captures", we stop if one side is ahead
44 * and doesn't need to capture, a form of pseudo-minimaxing.
45 *
46 ****************************************************************************/
47 {
48 int f, t, sq, piece, lastval;
49 int side, xside;
50 int swaplist[MAXPLYDEPTH], n;
51 BitBoard b, c, *d, *e, r;
52
53 f = FROMSQ (move);
54 t = TOSQ (move);
55 side = ((board.friends[white] & BitPosArray[f]) ? white : black);
56 xside = 1^side;
57
58 /* Squares attacking t for side and xside */
59 b = AttackTo (t, side);
60 c = AttackTo (t, xside);
61 CLEARBIT(b, f);
62 if (xray[cboard[f]])
63 AddXrayPiece (t, f, side, &b, &c);
64
65 d = board.b[side];
66 e = board.b[xside];
67 if (move & PROMOTION)
68 {
69 swaplist[0] = Value[PROMOTEPIECE (move)] - ValueP;
70 lastval = -Value[PROMOTEPIECE (move)];
71 }
72 else
73 {
74 swaplist[0] = (move & ENPASSANT ? ValueP : Value[cboard[t]]);
75 lastval = -Value[cboard[f]];
76 }
77 n = 1;
78 while (1)
79 {
80 if (c == NULLBITBOARD)
81 break;
82 for (piece = pawn; piece <= king; piece++)
83 {
84 r = c & e[piece];
85 if (r)
86 {
87 sq = leadz (r);
88 CLEARBIT (c, sq);
89 if (xray[piece])
90 AddXrayPiece (t, sq, xside, &c, &b);
91 swaplist[n] = swaplist[n-1] + lastval;
92 n++;
93 lastval = Value[piece];
94 break;
95 }
96 }
97
98 if (b == NULLBITBOARD)
99 break;
100 for (piece = pawn; piece <= king; piece++)
101 {
102 r = b & d[piece];
103 if (r)
104 {
105 sq = leadz (r);
106 CLEARBIT (b, sq);
107 if (xray[piece])
108 AddXrayPiece (t, sq, side, &b, &c);
109 swaplist[n] = swaplist[n-1] + lastval;
110 n++;
111 lastval = -Value[piece];
112 break;
113 }
114 }
115 }
116
117 /****************************************************************************
118 *
119 * At this stage, we have the swap scores in a list. We just need to
120 * mini-max the scores from the bottom up to the top of the list.
121 *
122 ****************************************************************************/
123 --n;
124 while (n)
125 {
126 if (n & 1)
127 {
128 if (swaplist[n] <= swaplist[n-1])
129 swaplist[n-1] = swaplist[n];
130 }
131 else
132 {
133 if (swaplist[n] >= swaplist[n-1])
134 swaplist[n-1] = swaplist[n];
135 }
136 --n;
137 }
138 return (swaplist[0]);
139 }
140
141
AddXrayPiece(int t,int sq,int side,BitBoard * b,BitBoard * c)142 void AddXrayPiece (int t, int sq, int side, BitBoard *b, BitBoard *c)
143 /***************************************************************************
144 *
145 * The purpose of this routine is to find a piece which attack through
146 * another piece (e.g. two rooks, Q+B, B+P, etc.) Side is the side attacking
147 * the square where the swapping is to be done.
148 *
149 ***************************************************************************/
150 {
151 int dir, nsq, piece;
152 BitBoard a;
153
154 dir = directions[t][sq];
155 a = Ray[sq][dir] & board.blocker;
156 if (a == NULLBITBOARD)
157 return;
158 nsq = (t < sq ? leadz (a) : trailz (a));
159 piece = cboard[nsq];
160 if ((piece == queen) || (piece == rook && dir > 3) ||
161 (piece == bishop && dir < 4))
162 {
163 if (BitPosArray[nsq] & board.friends[side])
164 *b |= BitPosArray[nsq];
165 else
166 *c |= BitPosArray[nsq];
167 }
168 return;
169 }
170