diff --git a/Processes/QGSJetII/Interaction.cc b/Processes/QGSJetII/Interaction.cc
index d9b4c3cea53a6479330992d0bc195d6c838ac418..92288e76cec1d212a4ac21ee60bf2668d6d24ed1 100644
--- a/Processes/QGSJetII/Interaction.cc
+++ b/Processes/QGSJetII/Interaction.cc
@@ -22,6 +22,9 @@
 #include <corsika/setup/SetupTrajectory.h>
 #include <corsika/utl/COMBoost.h>
 
+#include <corsika/random/RNGManager.h>
+#include <corsika/random/UniformRealDistribution.h>
+
 #include <sstream>
 #include <string>
 #include <tuple>
@@ -211,6 +214,9 @@ namespace corsika::process::qgsjetII {
       int beamA = 0;
       if (particles::IsNucleus(corsikaBeamId)) beamA = vP.GetNuclearA();
 
+      const HEPEnergyType projectileEnergyLabPerNucleon =
+	particles::IsNucleus(corsikaBeamId) ? projectileEnergyLab/beamA : projectileEnergyLab;
+      
       cout << "Interaction: ebeam lab: " << projectileEnergyLab / 1_GeV << endl
            << "Interaction: pbeam lab: " << projectileMomentumLab.GetComponents() / 1_GeV
            << endl;
@@ -242,8 +248,8 @@ namespace corsika::process::qgsjetII {
         cross_section_of_components[i] = sigProd;
       }
 
-      const auto targetCode =
-          mediumComposition.SampleTarget(cross_section_of_components, fRNG);
+      const auto targetCode = 
+          mediumComposition.SampleTarget(cross_section_of_components, rng_);
       cout << "Interaction: target selected: " << targetCode << endl;
 
       int targetQgsCode = -1;
@@ -262,29 +268,39 @@ namespace corsika::process::qgsjetII {
         throw std::runtime_error("QgsjetII target outside range.");
 
       // beam id for qgsjetII
-      int kBeam = 2; // default: proton Shouldn't we randomize neutron/proton for nuclei?
-      if (corsikaBeamId != particles::Code::Nucleus) {
-        kBeam = process::qgsjetII::ConvertToQgsjetIIRaw(corsikaBeamId);
+      std::uniform_real_distribution<double> select;
+
+      QgsjetIICode qgsjet_beam_code;
+      if (corsikaBeamId == particles::Code::Nucleus) {	
+	if (select(rng_)>0.5)
+	  qgsjet_beam_code = QgsjetIICode::Proton;
+	else
+	  qgsjet_beam_code = QgsjetIICode::Neutron;
+      } else { // it is a nucleus
+        qgsjet_beam_code = process::qgsjetII::ConvertToQgsjetII(corsikaBeamId);
         // from conex
-        if (kBeam == 0) { // replace pi0 or rho0 with pi+/pi-
-          static int select = 1;
-          kBeam = select;
-          select *= -1;
+        if (qgsjet_beam_code == QgsjetIICode::Pi0 or
+	    qgsjet_beam_code == QgsjetIICode::Rho0) { // replace pi0 or rho0 with pi+/pi- in alternating sequence
+	  static QgsjetIICode alternate = QgsjetIICode::PiPlus;
+	  qgsjet_beam_code = alternate;
+	  alternate = (alternate == QgsjetIICode::PiPlus ? QgsjetIICode::PiMinus : QgsjetIICode::PiPlus);
         }
         // replace lambda by neutron
-        if (kBeam == 6)
-          kBeam = 3;
-        else if (kBeam == -6)
-          kBeam = -3;
-        // else if (abs(kBeam)>6) -> throw
+        if (qgsjet_beam_code == QgsjetIICode::Lambda0)
+          qgsjet_beam_code = QgsjetIICode::Neutron;
+        else if (qgsjet_beam_code == QgsjetIICode::Lambda0Bar)
+          qgsjet_beam_code = QgsjetIICode::AntiNeutron;
+        // else if (abs(qgsjet_beam_code)>6) -> throw
       }
 
+      int qgsjet_beam_code_int = static_cast<QgsjetIICodeIntType>(qgsjet_beam_code);
+      
       cout << "Interaction: "
            << " DoInteraction: E(GeV):" << projectileEnergyLab / 1_GeV << endl;
       count_++;
-      qgini_(projectileEnergyLab / 1_GeV, kBeam, projQgsCode, targetQgsCode);
+      qgini_(projectileEnergyLab / 1_GeV, qgsjet_beam_code_int, projQgsCode, targetQgsCode);
       // this is from CRMC, is this REALLY needed ???
-      qgini_(projectileEnergyLab / 1_GeV, kBeam, projQgsCode, targetQgsCode);
+      qgini_(projectileEnergyLab / 1_GeV, qgsjet_beam_code_int, projQgsCode, targetQgsCode);
       qgconf_();
       
       // bookkeeping
@@ -298,23 +314,32 @@ namespace corsika::process::qgsjetII {
       geometry::CoordinateSystem const zAxisFrame =
 	originalCS.RotateToZ(projectileMomentumLab);
       
-      // fragments
+      // nuclear projectile fragments
       QGSJetIIFragmentsStack qfs;
       for (auto& fragm : qfs) {
         particles::Code idFragm = particles::Code::Nucleus;
-        int A = fragm.GetFragmentSize();
+        const int A = fragm.GetFragmentSize();
         int Z = 0;
         switch (A) {
           case 1: { // proton/neutron
-            idFragm = particles::Code::Proton;
-
+	    std::uniform_real_distribution<double> select;
+	    if (select(rng_)>0.5) {
+	      idFragm = particles::Code::Proton;
+	      Z = 1;
+	    } else {
+	      idFragm = particles::Code::Neutron;
+	      Z = 0;
+	    }
+
+	    const HEPMassType projectileMass = particles::GetMass(idFragm);
+	      
 	    auto momentum = geometry::Vector(
 					     zAxisFrame,
 					     corsika::geometry::QuantityVector<hepmomentum_d>{0.0_GeV, 0.0_GeV,
-						 sqrt((projectileEnergyLab + particles::Proton::GetMass()) *
-						      (projectileEnergyLab - particles::Proton::GetMass()))});
+						 sqrt((projectileEnergyLab + projectileMass) *
+						      (projectileEnergyLab - projectileMass))});
 	    
-	    auto const energy = sqrt(momentum.squaredNorm() + square(particles::GetMass(idFragm)));	    
+	    auto const energy = sqrt(momentum.squaredNorm() + square(projectileMass));	    
 	    momentum.rebase(originalCS); // transform back into standard lab frame
 	    std::cout << "secondary fragment> id=" << idFragm << " p=" << momentum.GetComponents() << std::endl;
             auto pnew = vP.AddSecondary(
@@ -340,13 +365,14 @@ namespace corsika::process::qgsjetII {
         }
 
         if (idFragm == particles::Code::Nucleus) {
-	    auto momentum = geometry::Vector(
+	  const HEPMassType nucleusMass = particles::Proton::GetMass() * Z + particles::Neutron::GetMass() * (A-Z);	  
+	  auto momentum = geometry::Vector(
 					     zAxisFrame,
 					     geometry::QuantityVector<hepmomentum_d>{0.0_GeV, 0.0_GeV,
-						 sqrt((projectileEnergyLab + constants::nucleonMass * A) *
-						      (projectileEnergyLab - constants::nucleonMass * A))});
+						 sqrt((projectileEnergyLabPerNucleon*A + nucleusMass) *
+						      (projectileEnergyLabPerNucleon*A - nucleusMass))});
 	    
-	    auto const energy = sqrt(momentum.squaredNorm() + square(constants::nucleonMass*A));	    
+	    auto const energy = sqrt(momentum.squaredNorm() + square(nucleusMass));	    
 	    momentum.rebase(originalCS); // transform back into standard lab frame
 	    std::cout << "secondary fragment> id=" << idFragm << " p=" << momentum.GetComponents() << " A=" << A << " Z=" << Z << std::endl;
             auto pnew = vP.AddSecondary(
diff --git a/Processes/QGSJetII/Interaction.h b/Processes/QGSJetII/Interaction.h
index 3ae93106c50286fed7f9a06631e85b47e292d302..0b2804a237639dd4a31776a76cafc02956315c67 100644
--- a/Processes/QGSJetII/Interaction.h
+++ b/Processes/QGSJetII/Interaction.h
@@ -56,7 +56,7 @@ namespace corsika::process::qgsjetII {
     corsika::process::EProcessReturn DoInteraction(TProjectile&);
 
   private:
-    corsika::random::RNG& fRNG =
+    corsika::random::RNG& rng_ =
         corsika::random::RNGManager::GetInstance().GetRandomStream("qgran");
     const int maxMassNumber_ = 208;
   };
diff --git a/Processes/QGSJetII/qgsjet-II-04-codes.dat b/Processes/QGSJetII/qgsjet-II-04-codes.dat
index 9cb511ec092f7fdd875b8514b6d14d78b8e51db6..3550eed83ce3f847153b8e79f85646af0816a7e4 100644
--- a/Processes/QGSJetII/qgsjet-II-04-codes.dat
+++ b/Processes/QGSJetII/qgsjet-II-04-codes.dat
@@ -1,5 +1,5 @@
 # input file for particle conversion to/from QGSJet
-# the format of this file is: "corsika-identifier" "qgsjet-id" "hadron-class for x-section"
+# the format of this file is: "corsika-identifier" "qgsjet-id" 
 
 # class 0 (cannot interact)
 Electron    11 0