I think this is not a correct SEE implementation. Whenever you find a new attacker for the target square you always have the choice between "making the capture" and "standing pat" (i.e., doing nothing). So at any point in your loop over pieces attacking the target square (not just in the root!) you would have to calculate the outcome of the capture but then ignore it if it loses material (so in fact you would also need to modify your algorithm). Just like in QS. What you seem to do in the code shown above is to always make the capture with the lowest remaining attacker, until no more attackers are left. But that is incorrect because it does not consider standing pat. For instance if the last enemy piece that did a capture was a knight and your next attacker is a queen but the enemy has another knight as attacker (defender) then you must detect that QxN NxQ is worse than not capturing.flok wrote:Code: Select all
// xy are of the victim int Scene::getSEE(const int x, const int y, const ChessPiece *const attacker) const { const ChessPiece *const victim = b.getAt(x, y); const PlayerColor c = attacker -> getColor(); // bit 0...15: if set, then a white piece can walk over and/or attack this field, 16...31 black const uint32_t bits = ss.back().tcs.cells[y][x]; int see_val = victim -> getEvalVal(); int trophy_val = attacker -> getEvalVal(); PlayerColor sc = opponentColor(c); int so[] = { 0, 16 }; // where to start to search in the bit pattern. so[0] is for white constexpr int soe[] = { 16, 32 }; // where to stop searching. soe[0] is for white for(; so[sc] < soe[sc];) { // find a 1 bit while((bits & (1 << so[sc])) == 0) { // if end of pattern, stop searching if (++so[sc] == soe[sc]) break; } if (so[sc] >= soe[sc]) break; if (sc == c) see_val += trophy_val; else see_val -= trophy_val; // get eval val. bit number is an index in pieces[color][index] pointing to the // piece. trophy_val = sc == WHITE ? pieces[sc][so[sc]] -> getEvalVal() : pieces[sc][so[sc] - 16] -> getEvalVal(); // on to the next bit! so[sc]++; sc = opponentColor(sc); } return see_val; }
It is slightly harder to do that correctly with an iterative algorithm compared to the very simple recursive one, but of course it is possible (by definition).