
#define SEE_SIGNED_BAD_VALUE					(KNIGHT_VALUE-BISHOP_VALUE)
#define CLEAR_BIT_WITH_WARRANTY(src, bit)		(src = (src|bit) ^ bit)

int Board::SEE(Move *m, bool debug) {

	// init	
	uint to = m->To(),
		from = m->From(),
		mover = m->Piece(),
		capture = m->Capture(),
		is_prom	= m->IsPromote(),
		side = stm^1, square, type;
	int value, ptr = 0, swap_list[32];
	BitBoard occ, current, bishops, rooks,
		attackers, occ_l90, occ_l45, occ_r45;

	rooks	= piece[ROOK]   | piece[QUEEN];
	bishops = piece[BISHOP] | piece[QUEEN];

	occ		= occupied	   ^ BIT(from);
	occ_l90 = occupied_rl90 ^ BIT_L90(from);
	occ_r45 = occupied_rr45 ^ BIT_R45(from);
	occ_l45 = occupied_rl45 ^ BIT_L45(from);

	// build attackers list	
	attackers  = KING_ATT(to)	& piece[KING];
	attackers |= KNIGHT_ATT(to)	& piece[KNIGHT];	
	attackers |= ((Pawn[WHITE][to] & Black()) | (Pawn[BLACK][to] & White())) & piece[PAWN];
	attackers |= ((ATT_R45(to, occ_r45)		  | ATT_L45(to, occ_l45)) & bishops);			// bishop & queen
	attackers |= ((ATT_RANK(to, occ)		  | ATT_FILE(to, occ_l90))& rooks);				// rook & queen
		
	value = PIECE_VALUE(capture);
	if(is_prom)	value += PIECE_VALUE_PROMOTE(m->Promote());	
	if(!(attackers & Occupied(side)))	return value;	// opponent has no defenders	
	swap_list[ptr++] = value;
	value = PIECE_VALUE(mover);
	if(is_prom)	value += PIECE_VALUE_PROMOTE(m->Promote());	

	while(attackers & Occupied(side)) {
		for(type = PAWN; !(current = (attackers & piece[type] & occupied_by[side])) && type <= KING; type++)
			;
		square = ExtractFirstBit(current); 
		occ		^= BIT(square);

		// add hidden attackers
		if(type & 1) {	// hack: pawn , bishop or queen
			occ_r45 ^= BIT_R45(square);
			occ_l45 ^= BIT_L45(square);
			attackers |= ((ATT_R45(to, occ_r45) | ATT_L45(to, occ_l45)) & bishops);	// bishop & queen
		}
		if((type == ROOK) || (type == QUEEN)) {
			occ_l90 ^= BIT_L90(square);
			attackers |= ((ATT_RANK(to, occ)	  | ATT_FILE(to, occ_l90))& rooks);	// rook & queen
		}

		attackers &= occ;

		swap_list[ptr] = value - swap_list[ptr-1];
		value = PIECE_VALUE(type);
		side ^= 1;
		ptr++;

		if(type == KING && (attackers & occupied_by[side])) {      
			swap_list[ptr++] = PIECE_VALUE(KING);
			break;
		}
	}

	while(--ptr)		
		swap_list[ptr-1] = MIN( -swap_list[ptr], swap_list[ptr-1]);
	return swap_list[0];
}
/*
// slower variant
int Board::SEE3(Move *m, bool debug) {

	// init
	BitBoard attackers,
		pseudo_att_rooks,
		pseudo_att_bishops,		
		bishops,
		rooks,
		current;
	uint to = m->To(),
		from = m->From(),
		mover = m->Piece(),
		capture = m->Capture(),
		is_prom	= m->IsPromote(),
		side = stm^1, square, type;
	int value, ptr = 0, swap_list[32];
	rooks = piece[ROOK]   | piece[QUEEN];
	bishops = piece[BISHOP] | piece[QUEEN];

	// build attackers list
	attackers  = ROOK_ATT(to)	& rooks;
	attackers |= BishopAttacksFrom(to)	& bishops;	
	attackers |= KING_ATT(to)	& piece[KING];
	attackers |= KnightAttacksFrom(to)	& piece[KNIGHT];
	attackers |= ((Pawn[WHITE][to] & Black()) 
			    | (Pawn[BLACK][to] & White())) & piece[PAWN];	
	
	pseudo_att_bishops = BishopPseudoAttacksFrom(to);
	pseudo_att_rooks = RookPseudoAttacksFrom(to);
//	if(debug)	PrintBitBoard(stdout, attackers);
	
	// add hidden attackers
	// bishops	
	if((mover == PAWN && capture) || (mover == BISHOP) || (mover == QUEEN))
		attackers |= ((BISHOP_ATT_MODEL(to, BIT_R45(from), BIT_L45(from)) ^ pseudo_att_bishops) 
				& BishopAttacksFrom(from) & bishops);	
	// rooks
	if((mover == ROOK) || (mover == PAWN && !capture) || (mover == QUEEN))
		attackers |= ((ROOK_ATT_MODEL(to, BIT(from), BIT_L90(from)) ^ pseudo_att_rooks) 
				& ROOK_ATT(from) & rooks);	
	
	value = PIECE_VALUE(capture);
	if(is_prom)	value += PIECE_VALUE_PROMOTE(m->Promote());

	// opponent has no defenders	
//	if(debug)	PrintBitBoard(stdout, attackers);	
	if(!(attackers & Occupied(side)))	return value;
		
	swap_list[ptr++] = value;
	value = PIECE_VALUE(mover);
	if(is_prom)	value += PIECE_VALUE_PROMOTE(m->Promote());

	// delete moving piece		
	CLEAR_BIT_WITH_WARRANTY(attackers,	BIT(from)); 	
//	if(debug)	PrintBitBoard(stdout, attackers);

	while(attackers & Occupied(side)) {
		for(type = PAWN; !(current = (attackers & piece[type] & occupied_by[side])) && type <= KING; type++)
			;
		square = ExtractFirstBit(current);		
		CLEAR_BIT_WITH_WARRANTY(attackers,	BIT(square)); 

		// add x-ray attackers
		if(type & 1) // hack: pawn, bishop or queen
			attackers |= ((BISHOP_ATT_MODEL(to, BIT_R45(square), BIT_L45(square)) ^ pseudo_att_bishops) 
					& BishopAttacksFrom(square) & bishops);	
		if((type == ROOK) || (type == QUEEN))
			attackers |= ((ROOK_ATT_MODEL(to, BIT(square), BIT_L90(square)) ^ pseudo_att_rooks) 
					& ROOK_ATT(square) & rooks);

//		if(debug)	PrintBitBoard(stdout, attackers);
//		if(debug)	PrintBitBoard(stdout, BISHOP_ATT_MODEL(to, BIT_R45(square), BIT_L45(square)));
//		if(debug)	PrintBitBoard(stdout, pseudo_att_bishops);

		swap_list[ptr] = value - swap_list[ptr-1];
		value = PIECE_VALUE(type);
		side ^= 1;
		ptr++;

		if(type == KING && (attackers & occupied_by[side])) {      
			swap_list[ptr++] = PIECE_VALUE(KING);
			break;
		}
	}

	while(--ptr)		
		swap_list[ptr-1] = MIN( -swap_list[ptr], swap_list[ptr-1]);
	return swap_list[0];
}
*/