def topology_3_bonds_apart(covalent_bond_dict):
    """
    Map atom connectivity EXACTLY 3 bonds apart.

    See Amber20 manual Figure 14.1.

    Parameters
    ----------
    covalent_bond_dict : dict
        Per residue covalent connectivity.

    Returns
    -------
    dict
        Per residue 3 bonds apart connectivity.
    """
    x_bonds_apart = {}
    prevs = set()

    for res, residue_atoms in covalent_bond_dict.items():
        res_d = x_bonds_apart.setdefault(res, {})

        # for all atoms in the residue
        for atom in residue_atoms:
            xba = res_d.setdefault(atom, set())
            prevs.clear()
            prevs.add(atom)

            # for CA, H in N... one bond
            for subatom1 in set(residue_atoms[atom]).difference(prevs):
                prevs.add(subatom1)

                # for CB, HA in CA... two bonds
                for subatom2 in set(residue_atoms[subatom1]).difference(prevs):
                    prevs.add(subatom2)

                    # for HB1, HB2 in CB... three bonds
                    for subatom3 in set(residue_atoms[subatom2]).difference(prevs):
                        xba.add(subatom3)

    return x_bonds_apart