Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 33 | pmbaty | 1 | #include "chess.h" |
| 2 | #include "data.h" |
||
| 3 | /* last modified 05/16/14 */ |
||
| 4 | /* |
||
| 5 | ******************************************************************************* |
||
| 6 | * * |
||
| 7 | * Swap() is used to analyze capture moves to see whether or not they appear * |
||
| 8 | * to be profitable. The basic algorithm is extremely fast since it uses the* |
||
| 9 | * bitmaps to determine which squares are attacking the [target] square. * |
||
| 10 | * * |
||
| 11 | * The algorithm is quite simple. Using the attack bitmaps, we enumerate all* |
||
| 12 | * the pieces that are attacking [target] for either side. Then we simply * |
||
| 13 | * use the lowest piece (value) for the correct side to capture on [target]. * |
||
| 14 | * we continually "flip" sides taking the lowest piece each time. * |
||
| 15 | * * |
||
| 16 | * As a piece is used, if it is a sliding piece (pawn, bishop, rook or queen)* |
||
| 17 | * we remove the piece, then generate moves of bishop/queen or rook/queen * |
||
| 18 | * and then add those in to the attackers, removing any attacks that have * |
||
| 19 | * already been used. * |
||
| 20 | * * |
||
| 21 | ******************************************************************************* |
||
| 22 | */ |
||
| 23 | int Swap(TREE * RESTRICT tree, int move, int side) { |
||
| 24 | uint64_t attacks, temp = 0, toccupied = OccupiedSquares; |
||
| 25 | uint64_t bsliders = |
||
| 26 | Bishops(white) | Bishops(black) | Queens(white) | Queens(black); |
||
| 27 | uint64_t rsliders = |
||
| 28 | Rooks(white) | Rooks(black) | Queens(white) | Queens(black); |
||
| 29 | int attacked_piece, piece, nc = 1, swap_list[32]; |
||
| 30 | int source = From(move); |
||
| 31 | int target = To(move); |
||
| 32 | |||
| 33 | /* |
||
| 34 | ************************************************************ |
||
| 35 | * * |
||
| 36 | * Determine which squares attack <target> for each side. * |
||
| 37 | * initialize by placing the piece on <target> first in * |
||
| 38 | * the list as it is being captured to start things off. * |
||
| 39 | * * |
||
| 40 | ************************************************************ |
||
| 41 | */ |
||
| 42 | attacks = AttacksTo(tree, target); |
||
| 43 | attacked_piece = pcval[Captured(move)]; |
||
| 44 | /* |
||
| 45 | ************************************************************ |
||
| 46 | * * |
||
| 47 | * The first piece to capture on <target> is the piece * |
||
| 48 | * standing on <source>. * |
||
| 49 | * * |
||
| 50 | ************************************************************ |
||
| 51 | */ |
||
| 52 | side = Flip(side); |
||
| 53 | swap_list[0] = attacked_piece; |
||
| 54 | piece = Piece(move); |
||
| 55 | attacked_piece = pcval[piece]; |
||
| 56 | Clear(source, toccupied); |
||
| 57 | if (piece & 1) |
||
| 58 | attacks |= BishopAttacks(target, toccupied) & bsliders; |
||
| 59 | if (piece != king && (piece == pawn || piece & 4)) |
||
| 60 | attacks |= RookAttacks(target, toccupied) & rsliders; |
||
| 61 | /* |
||
| 62 | ************************************************************ |
||
| 63 | * * |
||
| 64 | * Now pick out the least valuable piece for the correct * |
||
| 65 | * side that is bearing on <target>. As we find one, we * |
||
| 66 | * update the attacks (if this is a sliding piece) to get * |
||
| 67 | * the attacks for any sliding piece that is lined up * |
||
| 68 | * behind the attacker we are removing. * |
||
| 69 | * * |
||
| 70 | * Once we know there is a piece attacking the last * |
||
| 71 | * capturing piece, add it to the swap list and repeat * |
||
| 72 | * until one side has no more captures. * |
||
| 73 | * * |
||
| 74 | ************************************************************ |
||
| 75 | */ |
||
| 76 | for (attacks &= toccupied; attacks; attacks &= toccupied) { |
||
| 77 | for (piece = pawn; piece <= king; piece++) |
||
| 78 | if ((temp = Pieces(side, piece) & attacks)) |
||
| 79 | break; |
||
| 80 | if (piece > king) |
||
| 81 | break; |
||
| 82 | toccupied ^= (temp & (0-temp)); // Pierre-Marie Baty -- fixed signedness warning |
||
| 83 | if (piece & 1) |
||
| 84 | attacks |= BishopAttacks(target, toccupied) & bsliders; |
||
| 85 | if (piece != king && piece & 4) |
||
| 86 | attacks |= RookAttacks(target, toccupied) & rsliders; |
||
| 87 | swap_list[nc] = -swap_list[nc - 1] + attacked_piece; |
||
| 88 | attacked_piece = pcval[piece]; |
||
| 89 | if (swap_list[nc++] - attacked_piece > 0) |
||
| 90 | break; |
||
| 91 | side = Flip(side); |
||
| 92 | } |
||
| 93 | /* |
||
| 94 | ************************************************************ |
||
| 95 | * * |
||
| 96 | * Starting at the end of the sequence of values, use a * |
||
| 97 | * "minimax" like procedure to decide where the captures * |
||
| 98 | * will stop. * |
||
| 99 | * * |
||
| 100 | ************************************************************ |
||
| 101 | */ |
||
| 102 | while (--nc) |
||
| 103 | swap_list[nc - 1] = -Max(-swap_list[nc - 1], swap_list[nc]); |
||
| 104 | return swap_list[0]; |
||
| 105 | } |
||
| 106 | |||
| 107 | /* last modified 05/16/14 */ |
||
| 108 | /* |
||
| 109 | ******************************************************************************* |
||
| 110 | * * |
||
| 111 | * SwapO() is used to analyze a move already made to see if it appears to be * |
||
| 112 | * safe. It is similar to Swap() except that the move has already been made * |
||
| 113 | * and we are checking to see whether the opponent can gain material by * |
||
| 114 | * capturing the piece just moved. * |
||
| 115 | * * |
||
| 116 | ******************************************************************************* |
||
| 117 | */ |
||
| 118 | int SwapO(TREE * RESTRICT tree, int move, int side) { |
||
| 119 | uint64_t attacks, temp = 0, toccupied = OccupiedSquares; |
||
| 120 | uint64_t bsliders = |
||
| 121 | Bishops(white) | Bishops(black) | Queens(white) | Queens(black); |
||
| 122 | uint64_t rsliders = |
||
| 123 | Rooks(white) | Rooks(black) | Queens(white) | Queens(black); |
||
| 124 | int attacked_piece, piece, nc = 1, swap_list[32]; |
||
| 125 | int target = To(move); |
||
| 126 | |||
| 127 | /* |
||
| 128 | ************************************************************ |
||
| 129 | * * |
||
| 130 | * Determine which squares attack <target> for each side. * |
||
| 131 | * initialize by placing the piece on <target> first in * |
||
| 132 | * the list as it is being captured to start things off. * |
||
| 133 | * * |
||
| 134 | ************************************************************ |
||
| 135 | */ |
||
| 136 | attacks = AttacksTo(tree, target); |
||
| 137 | attacked_piece = pcval[Piece(move)]; |
||
| 138 | /* |
||
| 139 | ************************************************************ |
||
| 140 | * * |
||
| 141 | * The first piece to capture on <target> is the piece * |
||
| 142 | * standing on that square. We have to find out the least * |
||
| 143 | * valuable attacker for that square first. * |
||
| 144 | * * |
||
| 145 | ************************************************************ |
||
| 146 | */ |
||
| 147 | side = Flip(side); |
||
| 148 | swap_list[0] = attacked_piece; |
||
| 149 | for (piece = pawn; piece <= king; piece++) |
||
| 150 | if ((temp = Pieces(side, piece) & attacks)) |
||
| 151 | break; |
||
| 152 | if (piece > king) |
||
| 153 | return 0; |
||
| 154 | toccupied ^= (temp & (0-temp)); // Pierre-Marie Baty -- fixed signedness warning |
||
| 155 | if (piece & 1) |
||
| 156 | attacks |= BishopAttacks(target, toccupied) & bsliders; |
||
| 157 | if (piece != king && piece & 4) |
||
| 158 | attacks |= RookAttacks(target, toccupied) & rsliders; |
||
| 159 | attacked_piece = pcval[piece]; |
||
| 160 | side = Flip(side); |
||
| 161 | /* |
||
| 162 | ************************************************************ |
||
| 163 | * * |
||
| 164 | * Now pick out the least valuable piece for the correct * |
||
| 165 | * side that is bearing on <target>. As we find one, we * |
||
| 166 | * update the attacks (if this is a sliding piece) to get * |
||
| 167 | * the attacks for any sliding piece that is lined up * |
||
| 168 | * behind the attacker we are removing. * |
||
| 169 | * * |
||
| 170 | * Once we know there is a piece attacking the last * |
||
| 171 | * capturing piece, add it to the swap list and repeat * |
||
| 172 | * until one side has no more captures. * |
||
| 173 | * * |
||
| 174 | ************************************************************ |
||
| 175 | */ |
||
| 176 | for (attacks &= toccupied; attacks; attacks &= toccupied) { |
||
| 177 | for (piece = pawn; piece <= king; piece++) |
||
| 178 | if ((temp = Pieces(side, piece) & attacks)) |
||
| 179 | break; |
||
| 180 | if (piece > king) |
||
| 181 | break; |
||
| 182 | toccupied ^= (temp & (0-temp)); // Pierre-Marie Baty -- fixed signedness warning |
||
| 183 | if (piece & 1) |
||
| 184 | attacks |= BishopAttacks(target, toccupied) & bsliders; |
||
| 185 | if (piece != king && piece & 4) |
||
| 186 | attacks |= RookAttacks(target, toccupied) & rsliders; |
||
| 187 | swap_list[nc] = -swap_list[nc - 1] + attacked_piece; |
||
| 188 | attacked_piece = pcval[piece]; |
||
| 189 | if (swap_list[nc++] - attacked_piece > 0) |
||
| 190 | break; |
||
| 191 | side = Flip(side); |
||
| 192 | } |
||
| 193 | /* |
||
| 194 | ************************************************************ |
||
| 195 | * * |
||
| 196 | * Starting at the end of the sequence of values, use a * |
||
| 197 | * "minimax" like procedure to decide where the captures * |
||
| 198 | * will stop. * |
||
| 199 | * * |
||
| 200 | ************************************************************ |
||
| 201 | */ |
||
| 202 | while (--nc) |
||
| 203 | swap_list[nc - 1] = -Max(-swap_list[nc - 1], swap_list[nc]); |
||
| 204 | return swap_list[0]; |
||
| 205 | } |