// connected_threat() tests whether it is safe to forward prune a move or if // is somehow connected to the threat move returned by null search. static bool connected_threat(Position pos, Move m, Move threat) { Debug.Assert(Utils.is_ok_M(m)); Debug.Assert(Utils.is_ok_M(threat)); Debug.Assert(!pos.is_capture_or_promotion(m)); Debug.Assert(!pos.is_passed_pawn_push(m)); Square mfrom, mto, tfrom, tto; mfrom = Utils.from_sq(m); mto = Utils.to_sq(m); tfrom = Utils.from_sq(threat); tto = Utils.to_sq(threat); // Case 1: Don't prune moves which move the threatened piece if (mfrom == tto) return true; // Case 2: If the threatened piece has value less than or equal to the // value of the threatening piece, don't prune moves which defend it. if (pos.is_capture(threat) && (Position.PieceValueMidgame[pos.piece_on(tfrom)] >= Position.PieceValueMidgame[pos.piece_on(tto)] || Utils.type_of(pos.piece_on(tfrom)) == PieceTypeC.KING) && pos.move_attacks_square(m, tto)) return true; // Case 3: If the moving piece in the threatened move is a slider, don't // prune safe moves which block its ray. if (piece_is_slider(pos.piece_on(tfrom)) && (Utils.bit_is_set(Utils.between_bb(tfrom, tto), mto) != 0) && pos.see(m, true) >= 0) return true; return false; }