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