diff --git a/aicrowd.json b/aicrowd.json
index c7c8e156dea73d2a09246fd32a0a379744a42011..fae008f5d9dde9ddfa218d3d2ae47573fe80e426 100644
--- a/aicrowd.json
+++ b/aicrowd.json
@@ -3,6 +3,6 @@
   "grader_id": "aicrowd_flatland_challenge_2019",
   "authors": ["mugurelionut"],
   "description": "Flatland Challenge Agent - various techniques.",
-  "debug" : false
+  "debug" : true
 }
 
diff --git a/r2sol.cc b/r2sol.cc
index 431cbd738f66f7042d2868c479b35556add29cb4..5877130adf6b6c05f1cd3956332c37fff9682400 100644
--- a/r2sol.cc
+++ b/r2sol.cc
@@ -37,6 +37,7 @@ using namespace std;
 #define ZERO 0.000001
 #define ONE 0.999999
 #define USE_SPACING_TO_AVOID_DEADLOCKS 1
+//#define USE_STRICT_SPACING_TO_AVOID_DEADLOCKS 0
 #define MIN_TINIT_FOR_SAVE_DATA_FOR_REPLAY 1000000
 
 class Xor128 {
@@ -663,7 +664,7 @@ bool CanEnterCell(int aid, int t, int from, int to, const int covered_by[][MAXNO
   if (agent_aid.target_node == to) {
     if (is_covered1 == is_covered_idx && aid1 < aid) return false;
     if (is_covered2 == is_covered_idx && aid2 > aid) return false;
-    if (USE_SPACING_TO_AVOID_DEADLOCKS && is_covered1 == is_covered_idx && (agent_aid.cturns >= 2 || agent[aid2].cturns >= 2)) return false;
+    //if (USE_SPACING_TO_AVOID_DEADLOCKS && is_covered1 == is_covered_idx && (agent_aid.cturns >= 2 || agent[aid2].cturns >= 2)) return false;
   } else {
     if (is_covered1 == is_covered_idx) return false;
     if (is_covered2 == is_covered_idx && aid2 > aid) return false;
@@ -687,7 +688,7 @@ bool CanEnterCell(int aid, int t, int from, int to, const int covered_by[][MAXNO
       const auto& tmp_path_aid5 = tmp_path[aid5];
       assert(tmp_path_aid5.tmax > TINIT);
       if (aid5 > aid && tmp_path_aid5.tmax == t && tmp_path_aid5.p[t].node == to) return false;
-      if (USE_SPACING_TO_AVOID_DEADLOCKS && tmp_path_aid5.tmax == t && tmp_path_aid5.p[t].node == to && (agent_aid.cturns >= 2 || agent_aid5.cturns >= 2)) return false;
+      //if (USE_SPACING_TO_AVOID_DEADLOCKS && tmp_path_aid5.tmax == t && tmp_path_aid5.p[t].node == to && (agent_aid.cturns >= 2 || agent_aid5.cturns >= 2)) return false;
       if (aid5 < aid && tmp_path_aid5.tmax == t + 1 && tmp_path_aid5.p[t + 1].node == to) return false;
     }
   }
@@ -704,7 +705,24 @@ int tend_ongoing_move[NMAX];
 
 bool OverlapsOngoingMove(int t1, int t2, int node, const int covered_by[][MAXNODES], const int is_covered[][MAXNODES], int is_covered_idx, const Path tmp_path[], int tmax_at_poz_node[]) {
   if (t1 < tend_ongoing_move[node]) return true;
+  const int aid_t1 = is_covered[t1][node] == is_covered_idx ? covered_by[t1][node] : -1;
+
+  for (int tend = t1 + 1; tend <= t2; ++tend) {
+    if (is_covered[tend][node] == is_covered_idx) {
+      const auto& aid_tend = covered_by[tend][node];
+      if (aid_tend != aid_t1 || is_covered[tend - 1][node] != is_covered_idx) return true;
+    }
+  }
+
   for (int tend = t2 + 1; tend <= t2 + 3 && tend <= T; ++tend) {
+    if (is_covered[tend][node] == is_covered_idx) {
+      const auto& aid = covered_by[tend][node];
+      const auto& agent_aid = agent[aid];
+      if (tend - agent_aid.cturns < t2 && (aid != aid_t1 || is_covered[tend - 1][node] != is_covered_idx)) return true;
+    }
+  }
+
+  /*for (int tend = t2 + 1; tend <= t2 + 3 && tend <= T; ++tend) {
     if (is_covered[tend][node] == is_covered_idx) {
       const auto& aid = covered_by[tend][node];
       const auto& agent_aid = agent[aid];
@@ -717,8 +735,10 @@ bool OverlapsOngoingMove(int t1, int t2, int node, const int covered_by[][MAXNOD
       const auto& curr_node_aid_tend = agent[aid_tend].poz_node;
       if (curr_node_aid_tend != node || tmax_at_poz_node[aid_tend] < tend) return true;
     }
-  }
-  const auto& target_node_agents_node = target_node_agents[node];
+  }*/
+  
+  
+  /*const auto& target_node_agents_node = target_node_agents[node];
   const auto& num_target_node_agents_node = num_target_node_agents[node];
   for (int idx = num_target_node_agents_node - 1; idx >= 0; --idx) {
     const auto& aid5 = target_node_agents_node[idx];
@@ -729,7 +749,8 @@ bool OverlapsOngoingMove(int t1, int t2, int node, const int covered_by[][MAXNOD
     if (tmp_path_aid5.p[tmp_path_aid5.tmax].node == agent_aid5.target_node && t1 < tmp_path_aid5.tmax && tmp_path_aid5.tmax <= t2) {
       return true;
     }
-  }
+  }*/
+  
   return false;
 }
 
@@ -1135,6 +1156,9 @@ void CheckNonDeadlockPaths() {
   }
 }
 
+const double kScoreExponent = 2.0;
+const double kMaxTmaxWeight = 1e9;
+
 void RandomPermutations(int tid, int ntries) {
   auto& pused_tid = pused[tid];
   auto& perm_tid = perm[tid];
@@ -1163,13 +1187,30 @@ void RandomPermutations(int tid, int ntries) {
 
   for (int trial = 1; trial <= ntries; ++trial) {
     if (tid == 0 && trial <= 1) {
+      if (trial == 2) reverse(shpaths_sorted.begin(), shpaths_sorted.end());
       for (int i = 0; i < N; ++i) perm_tid[i] = shpaths_sorted[i].second;
-      reverse(shpaths_sorted.begin(), shpaths_sorted.end());
+      if (trial == 2) reverse(shpaths_sorted.begin(), shpaths_sorted.end());
     } else {
       for (int i = 0; i < N; ++i) pused_tid[i] = 0;
-      int idx = 0;
-      if ((trial & 1) == 1) {
-        /*for (int cturns = MAX_CTURNS - 1; cturns >= 0; --cturns) {
+      /*int idx = 0;
+      for (int i = 0; i < N; ++i) {
+        do {
+          perm_tid[idx] = xor128_tid.rand() % N;
+        } while (pused_tid[perm_tid[idx]]);
+        pused_tid[perm_tid[idx++]] = 1;
+      }*/
+      const int kMaxSwapDistance = 2;
+      for (int idx = 0; idx < N; ++idx) {
+        const int idx2min = max(0, idx - kMaxSwapDistance);
+        const int idx2max = min(N - 1, idx + kMaxSwapDistance);
+        const int idx2 = idx2min + (xor128_tid.rand() % (idx2max - idx2min + 1));
+        const int tmp = shpaths_sorted[idx].second;
+        shpaths_sorted[idx].second = shpaths_sorted[idx2].second;
+        shpaths_sorted[idx2].second = tmp;
+      }
+      for (int i = 0; i < N; ++i) perm_tid[i] = shpaths_sorted[i].second;      
+      /*if ((trial & 1) == 0) {
+        for (int cturns = MAX_CTURNS - 1; cturns >= 0; --cturns) {
           const auto& cturns_agents_cturns = cturns_agents[cturns];
           const auto& num_cturns_agents_cturns = num_cturns_agents[cturns];
           for (int i = 0; i < num_cturns_agents_cturns; ++i) {
@@ -1178,12 +1219,6 @@ void RandomPermutations(int tid, int ntries) {
             } while (pused_tid[perm_tid[idx]]);
             pused_tid[perm_tid[idx++]] = 1;
           }
-        }*/
-        for (int i = 0; i < N; ++i) {
-          do {
-            perm_tid[idx] = xor128_tid.rand() % N;
-          } while (pused_tid[perm_tid[idx]]);
-          pused_tid[perm_tid[idx++]] = 1;
         }
       } else {
         for (int cturns = 0; cturns < MAX_CTURNS; ++cturns) {
@@ -1196,16 +1231,6 @@ void RandomPermutations(int tid, int ntries) {
             pused_tid[perm_tid[idx++]] = 1;
           }
         }
-      }
-      /*for (int cturns = MAX_CTURNS - 1; cturns >= 0; --cturns) {
-        const auto& cturns_agents_cturns = cturns_agents[cturns];
-        const auto& num_cturns_agents_cturns = num_cturns_agents[cturns];
-        for (int i = 0; i < num_cturns_agents_cturns; ++i) {
-          do {
-            perm_tid[idx] = cturns_agents_cturns[xor128_tid.rand() % num_cturns_agents_cturns];
-          } while (pused_tid[perm_tid[idx]]);
-          pused_tid[perm_tid[idx++]] = 1;
-        }
       }*/
     }
     ++is_covered_idx_tid;
@@ -1251,7 +1276,7 @@ void RandomPermutations(int tid, int ntries) {
     
     if (RunConsistencyChecks(tmp_path_tid, covered_by_tid, is_covered_tid, is_covered_idx_tid, false)) {   
       int num_done_agents = 0;
-      double cost = 0.0;
+      double cost = 0.0, max_tmax = 0.0;
       for (int aid = 0; aid < N; ++aid) {
         const auto& agent_aid = agent[aid];
         if (agent_aid.status == DONE_REMOVED) continue;      
@@ -1260,11 +1285,13 @@ void RandomPermutations(int tid, int ntries) {
         if (tmp_path_tid_aid.tmax > TINIT && tmp_path_tid_aid.tmax <= T && tmp_path_tid_aid.p[tmp_path_tid_aid.tmax].node == agent_aid.target_node) {
           ++num_done_agents;
           //cost += agent_aid.speed * (tmp_path_tid_aid.tmax - TINIT);
-          cost += pow(tmp_path_tid_aid.tmax, 3.0);
+          cost += pow(tmp_path_tid_aid.tmax, kScoreExponent);
+          if (tmp_path_tid_aid.tmax > max_tmax) max_tmax = tmp_path_tid_aid.tmax;
         } else {
           //cost += agent_aid.speed * (T - TINIT);
         }
       }
+      cost += max_tmax * kMaxTmaxWeight;
       {
         lock_guard<mutex> guard(m);
         DBG(3, "[RandomPermutations] rerun=%d tid=%d trial=%d/%d nda=%d/%d cost=%.6lf: maxda=%d/%d minc=%.6lf time=%.3lf\n", rerun, tid, trial, ntries, num_done_agents, N, cost, MAX_DONE_AGENTS, N, MIN_COST, GetTime() - TSTART);
@@ -1288,7 +1315,7 @@ void RegenerateFullPlan() {
   updated_best_solution = true;
   rerun = 0;
 
-  const int kMaxReruns = 3;//TINIT == 0 ? 4 : 3;
+  const int kMaxReruns = 4;
   
   while (updated_best_solution && rerun < kMaxReruns) {
     updated_best_solution = false;
@@ -1316,7 +1343,7 @@ void RegenerateFullPlan() {
       if (max_threads >= 2) th = new thread*[max_threads - 1];
 
       // Random Permutations.
-      const int kNumRandomPermutations = 7;//min(6 * 200 * 2560 / (N * T), 25);
+      const int kNumRandomPermutations = 10;//min(6 * 200 * 2560 / (N * T), 25);
       if (max_threads >= 2) {
         for (int tid = 0; tid + 1 < max_threads; ++tid) th[tid] = new thread([tid, kNumRandomPermutations]{
           RandomPermutations(tid, kNumRandomPermutations);
@@ -1925,13 +1952,14 @@ bool AdjustIPaths() {
     if (path_aid.p[path_aid.tmax].node == agent_aid.target_node) {
       ++MAX_DONE_AGENTS;
       //MIN_COST += agent_aid.speed * (path_aid.tmax - TINIT);
-      MIN_COST += pow(path_aid.tmax, 3.0);
+      MIN_COST += pow(path_aid.tmax, kScoreExponent);
       if (path_aid.tmax > new_max_tmax) new_max_tmax = path_aid.tmax;
     } else {
       assert(path_aid.tmax == T);
       //MIN_COST += agent_aid.speed * (path_aid.tmax - TINIT);
     }
   }
+  MIN_COST += new_max_tmax * kMaxTmaxWeight;
   
   const bool changed_important_data = MAX_DONE_AGENTS != num_planned || new_max_tmax > max_tmax;
   if (changed_important_data) {
@@ -2111,7 +2139,7 @@ void GetMoves(const char* testid, bool replay_mode = false) {
       updated_paths_ok = AdjustIPaths();
       ++num_adjust_ipaths_without_full_plan_regeneration;
     }
-    const int kMaxNumAdjustIPathsWithoutFullPlanRegenartion = 6;//10;
+    const int kMaxNumAdjustIPathsWithoutFullPlanRegenartion = 5;//10;
     if (!updated_paths_ok || num_adjust_ipaths_without_full_plan_regeneration > kMaxNumAdjustIPathsWithoutFullPlanRegenartion) {
       RegenerateFullPlan();
       if (TINIT >= 1 && any_best_solution_updates) AdjustIPaths();
@@ -2132,8 +2160,6 @@ void GetMoves(const char* testid, bool replay_mode = false) {
       }
     }
   }*/
-
-//  if (TINIT == 417) exit(1);
 }
 
 }
@@ -2146,11 +2172,3 @@ int main() {
   SOLVE::GetMoves("1", true);
   return 0;
 }
-
-/*
-0 100 74.0740740741 -55460.4166667195
-1 100 71.4285714286 -45245.7500000240
-2 56 46.2809917355 -47283.7500000259
-3 80 100.0000000000 -12941.6666666694
-4 96 61.9354838710 -97453.3333331954
-*/
diff --git a/r2sol.exe b/r2sol.exe
index 15948abf4d1dd903cd47060a5075f65990224a8c..4938556a36a5601f9f8c902603e778dfa64f8f75 100755
Binary files a/r2sol.exe and b/r2sol.exe differ
diff --git a/run_local.py b/run_local.py
index f20097bdd20d3c8759a96536a4a5824dc3ecdf82..4e9aba76a0261dde20dc6b4584f692f74d7e9a39 100644
--- a/run_local.py
+++ b/run_local.py
@@ -25,7 +25,7 @@ def GetTestParams(tid):
   return (seed, width, height, nr_trains, nr_cities, max_rails_between_cities, max_rails_in_cities, malfunction_rate, malfunction_min_duration, malfunction_max_duration)
 
 def ShouldRunTest(tid):
-  return tid >= 5
+  #return tid >= 5
   #return tid == 2
   return True
 
@@ -41,7 +41,7 @@ d_base = {}
 f = open("scores.txt", "r")
 for line in f.readlines():
   lsplit = line.split(" ")
-  if len(lsplit) == 4:
+  if len(lsplit) >= 4:
     test_id = int(lsplit[0])
     num_done_agents = int(lsplit[1])
     percentage_num_done_agents = float(lsplit[2])
@@ -104,7 +104,6 @@ for test_id in range(NUM_TESTS):
 
     obs = next_obs.copy()
     if done['__all__']:
-      print ("done")
       break
 
   num_done_agents = 0
@@ -124,8 +123,11 @@ for test_id in range(NUM_TESTS):
   total_base_percentage_num_done_agents += base_percentage_num_done_agents
   total_base_score += base_score
 
-  print("\n### test_id=%d nda=%d(dif=%d) pnda=%.6f(dif=%.6f) score=%.6f(dif=%.6f) avg_nda=%.6f(dif=%.6f) avg_sc=%.6f(dif=%.6f)\n" % (test_id, num_done_agents, num_done_agents - base_num_done_agents, percentage_num_done_agents, percentage_num_done_agents - base_percentage_num_done_agents, score, score - base_score, total_percentage_num_done_agents / num_tests, (total_percentage_num_done_agents - total_base_percentage_num_done_agents) / num_tests, total_score / num_tests, (total_score - total_base_score) / num_tests))
-  f.write("%d %d% .10f %.10f\n" % (test_id, num_done_agents, percentage_num_done_agents, score))
+  avg_nda = total_percentage_num_done_agents / num_tests
+  avg_nda_dif = (total_percentage_num_done_agents - total_base_percentage_num_done_agents) / num_tests
+
+  print("\n### test_id=%d nda=%d(dif=%d) pnda=%.6f(dif=%.6f) score=%.6f(dif=%.6f) avg_nda=%.6f(dif=%.6f) avg_sc=%.6f(dif=%.6f)\n" % (test_id, num_done_agents, num_done_agents - base_num_done_agents, percentage_num_done_agents, percentage_num_done_agents - base_percentage_num_done_agents, score, score - base_score, avg_nda, avg_nda_dif, total_score / num_tests, (total_score - total_base_score) / num_tests))
+  f.write("%d %d% .10f %.10f %.10f %.10f\n" % (test_id, num_done_agents, percentage_num_done_agents, score, avg_nda, avg_nda_dif))
   f.flush()
 
 f.close()
diff --git a/tmp-scores.txt b/tmp-scores.txt
index 2137d557937242d8675770fed4c66ba7ab784b2b..6a0da14a089b57720004df5913185ab60202631b 100644
--- a/tmp-scores.txt
+++ b/tmp-scores.txt
@@ -1,10 +1,5 @@
-5 126 96.1832061069 -44149.0833333480
-6 138 79.7687861272 -70195.6666667112
-7 87 63.9705882353 -46680.9166666893
-8 74 61.6666666667 -44158.7500000220
-9 55 35.9477124183 -79448.2499999903
-10 81 48.2142857143 -97614.4166665799
-11 91 87.5000000000 -18943.1666666680
-12 61 55.4545454545 -50918.2500000281
-13 122 76.7295597484 -53732.9166667196
-14 75 60.9756097561 -67341.6666667139
+0 103 76.2962962963 -56746.5833333795 76.2962962963 -0.7407407407
+1 94 67.1428571429 -47095.9166666898 71.7195767196 -2.5132275132
+2 70 57.8512396694 -45232.7500000205 67.0967977029 2.1812643025
+3 80 100.0000000000 -15218.8333333374 75.3225982771 1.6359482269
+4 100 64.5161290323 -91272.9166665628 73.1613044282 1.3087585815