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