The pseudocode you copied from the wiki is just the easiest way to make you understand SEE. It is NOT used in a real chess engine, because building a
swap list would be more efficient.
You should check Stockfish. I'll give you some hints here.
- Goto position.cpp.
- Find the function
Value Position::see(Move m) const. This is where SEE is implemented
Check this loop:
assert(slIndex < 32);
// Add the new entry to the swap list
swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[MG][captured];
// Locate and remove the next least valuable attacker
captured = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
stm = ~stm;
stmAttackers = attackers & pieces(stm);
} while (stmAttackers && (captured != KING || (--slIndex, false))); // Stop before a king capture
Stockfish doesn't do exactly what your pseudocode does. It loops for all for possible attackers from the least powerful (
min_attacker). For each attacker, the engine checks it's value (
PieceValues[MG]) and add it to the swap list. The swap list will then be looped over for nega-max:
// Having built the swap list, we negamax through it to find the best
// achievable score from the point of view of the side to move.
swapList[slIndex - 1] = std::min(-swapList[slIndex], swapList[slIndex - 1]);
Don't be afraid of the while loop, all it does to check if an exchange is good or not. In fact, the wikipedia you stated has the reasoning:
This uses a trick, equivalent to negamax in tree search, where the loss for the current side is the gain for the opposite side. This can be seen in the expression piece_just_captured() - see(square); which is the value of the piece captured (piece_just_captured()) minus the gain that the opponent might make after the move by recapturing. If that term becomes negative, one would better choose standing pat rather than to capture, which can be done by a conditional assignment, or by a max function with zero as second argument.