diff --git a/.gitignore b/.gitignore
index c8934be34fad46d6839c35f5eb8f3e1630305adc..2f544ae078f30091e39c58abf2e6c731a9979bd3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,7 +11,7 @@ __pycache__/
 env/
 build/
 develop-eggs/
-dist/
+# dist/
 downloads/
 eggs/
 .eggs/
diff --git a/dist/flatland_rl-3.0.0-py2.py3-none-any.whl b/dist/flatland_rl-3.0.0-py2.py3-none-any.whl
new file mode 100644
index 0000000000000000000000000000000000000000..8000ae9255d697b02a46e5c4e4df0bd798836d7b
Binary files /dev/null and b/dist/flatland_rl-3.0.0-py2.py3-none-any.whl differ
diff --git a/flatland/cli.py b/flatland/cli.py
index 2bd5cca2730772592f6a345d3328f8c6ae1d1df8..6dfc6c7de1a93afedf83e564d5962b588632b164 100644
--- a/flatland/cli.py
+++ b/flatland/cli.py
@@ -10,7 +10,7 @@ import redis
 
 from flatland.envs.rail_env import RailEnv
 from flatland.envs.rail_generators import complex_rail_generator
-from flatland.envs.schedule_generators import complex_schedule_generator
+from flatland.envs.line_generators import complex_line_generator
 from flatland.evaluators.service import FlatlandRemoteEvaluationService
 from flatland.utils.rendertools import RenderTool
 
@@ -22,7 +22,7 @@ def demo(args=None):
         nr_start_goal=10,
         nr_extra=1,
         min_dist=8,
-        max_dist=99999), schedule_generator=complex_schedule_generator(), number_of_agents=5)
+        max_dist=99999), line_generator=complex_line_generator(), number_of_agents=5)
 
     env._max_episode_steps = int(15 * (env.width + env.height))
     env_renderer = RenderTool(env)
diff --git a/flatland/envs/line_generators.py b/flatland/envs/line_generators.py
index 51e9fae2736dd147b33cb23fcaeda496a7865b16..e7d6ac170aa82f86e75fe291c454648defedabd9 100644
--- a/flatland/envs/line_generators.py
+++ b/flatland/envs/line_generators.py
@@ -94,13 +94,15 @@ class SparseLineGen(BaseLineGen):
         agents_target = []
         agents_direction = []
 
-        for agent_pair_idx in range(0, num_agents, 2):
-            infeasible_agent = True
-            tries = 0
-            while infeasible_agent:
-                tries += 1
-                infeasible_agent = False
 
+        city1, city2 = None, None
+        city1_num_stations, city2_num_stations = None, None
+        city1_possible_orientations, city2_possible_orientations = None, None
+
+
+        for agent_idx in range(num_agents):
+
+            if (agent_idx % 2 == 0):
                 # Setlect 2 cities, find their num_stations and possible orientations
                 city_idx = np_random.choice(len(city_positions), 2, replace=False)
                 city1 = city_idx[0]
@@ -111,33 +113,32 @@ class SparseLineGen(BaseLineGen):
                                                 (city_orientation[city1] + 2) % 4]
                 city2_possible_orientations = [city_orientation[city2],
                                                 (city_orientation[city2] + 2) % 4]
+
                 # Agent 1 : city1 > city2, Agent 2: city2 > city1
-                agent1_start_idx = ((2 * np_random.randint(0, 10))) % city1_num_stations
-                agent1_target_idx = ((2 * np_random.randint(0, 10)) + 1) % city2_num_stations
-                agent2_start_idx = ((2 * np_random.randint(0, 10))) % city2_num_stations
-                agent2_target_idx = ((2 * np_random.randint(0, 10)) + 1) % city1_num_stations
+                agent_start_idx = ((2 * np_random.randint(0, 10))) % city1_num_stations
+                agent_target_idx = ((2 * np_random.randint(0, 10)) + 1) % city2_num_stations
+
+                agent_start = train_stations[city1][agent_start_idx]
+                agent_target = train_stations[city2][agent_target_idx]
+
+                agent_orientation = np_random.choice(city1_possible_orientations)
+
+
+            else:
+                agent_start_idx = ((2 * np_random.randint(0, 10))) % city2_num_stations
+                agent_target_idx = ((2 * np_random.randint(0, 10)) + 1) % city1_num_stations
                 
-                agent1_start = train_stations[city1][agent1_start_idx]
-                agent1_target = train_stations[city2][agent1_target_idx]
-                agent2_start = train_stations[city2][agent2_start_idx]
-                agent2_target = train_stations[city1][agent2_target_idx]
+                agent_start = train_stations[city2][agent_start_idx]
+                agent_target = train_stations[city1][agent_target_idx]
                             
-                agent1_orientation = np_random.choice(city1_possible_orientations)
-                agent2_orientation = np_random.choice(city2_possible_orientations)
+                agent_orientation = np_random.choice(city2_possible_orientations)
 
-                # check path exists then break if tries > 100
-                if tries >= 100:
-                    warnings.warn("Did not find any possible path, check your parameters!!!")
-                    break
             
             # agent1 details
-            agents_position.append((agent1_start[0][0], agent1_start[0][1]))
-            agents_target.append((agent1_target[0][0], agent1_target[0][1]))
-            agents_direction.append(agent1_orientation)
-            # agent2 details
-            agents_position.append((agent2_start[0][0], agent2_start[0][1]))
-            agents_target.append((agent2_target[0][0], agent2_target[0][1]))
-            agents_direction.append(agent2_orientation)
+            agents_position.append((agent_start[0][0], agent_start[0][1]))
+            agents_target.append((agent_target[0][0], agent_target[0][1]))
+            agents_direction.append(agent_orientation)
+
 
         if self.speed_ratio_map:
             speeds = speed_initialization_helper(num_agents, self.speed_ratio_map, seed=_runtime_seed, np_random=np_random)
diff --git a/flatland/envs/persistence.py b/flatland/envs/persistence.py
index b8354078f68705e2d3757a61626c03df2ac9dc4c..41f352e70017f1f37bb66abaa911d25725618836 100644
--- a/flatland/envs/persistence.py
+++ b/flatland/envs/persistence.py
@@ -163,7 +163,7 @@ class RailEnvPersister(object):
             # remove the legacy key
             del env_dict["agents_static"]
         elif "agents" in env_dict:
-            env_dict["agents"] = [EnvAgent(*d[0:12]) for d in env_dict["agents"]]
+            env_dict["agents"] = [EnvAgent(*d[0:len(d)]) for d in env_dict["agents"]]
 
         return env_dict
 
diff --git a/flatland/envs/rail_env.py b/flatland/envs/rail_env.py
index 636cbb7bd56a046e6bf4884b3072a54895f188e9..eb62f0eca41fbca1e28bf55455829ef1566b0b24 100644
--- a/flatland/envs/rail_env.py
+++ b/flatland/envs/rail_env.py
@@ -23,7 +23,6 @@ from flatland.envs.rail_env_action import RailEnvActions
 from flatland.envs import malfunction_generators as mal_gen
 from flatland.envs import rail_generators as rail_gen
 from flatland.envs import line_generators as line_gen
-# NEW : Imports
 from flatland.envs.schedule_generators import schedule_generator
 from flatland.envs import persistence
 from flatland.envs import agent_chains as ac
@@ -199,8 +198,6 @@ class RailEnv(Environment):
             self.malfunction_generator = mal_gen.NoMalfunctionGen()
             self.malfunction_process_data = self.malfunction_generator.get_process_data()
         
-        if number_of_agents % 2 == 1:
-            raise ValueError("Odd number of agents is no longer supported, set number_of_agents to an even number")
         self.number_of_agents = number_of_agents
 
         # self.rail_generator: RailGenerator = rail_generator
diff --git a/flatland/evaluators/client.py b/flatland/evaluators/client.py
index 5471cd47e99b2b5f49031c2bebe3ab470331e32b..352dd54d118e65e6cec1d0182bbb1959280d6c60 100644
--- a/flatland/evaluators/client.py
+++ b/flatland/evaluators/client.py
@@ -266,7 +266,7 @@ class FlatlandRemoteClient(object):
             print("Current env path : ", test_env_file_path)
         self.current_env_path = test_env_file_path
         self.env = RailEnv(width=1, height=1, rail_generator=rail_from_file(test_env_file_path),
-                           schedule_generator=schedule_from_file(test_env_file_path),
+                           line_generator=line_from_file(test_env_file_path),
                            malfunction_generator_and_process_data=malfunction_from_file(test_env_file_path),
                            obs_builder_object=obs_builder_object)
 
diff --git a/flatland/evaluators/service.py b/flatland/evaluators/service.py
index 8e3b4155158d4fbce32a6e6868f0a5b72c85127b..92537282d1571ab14d6b009a0ec514d48bc2e6c2 100644
--- a/flatland/evaluators/service.py
+++ b/flatland/evaluators/service.py
@@ -50,7 +50,7 @@ m.patch()
 ########################################################
 
 # Don't proceed to next Test if the previous one didn't reach this mean completion percentage
-TEST_MIN_PERCENTAGE_COMPLETE_MEAN = float(os.getenv("TEST_MIN_PERCENTAGE_COMPLETE_MEAN", 0.25))
+TEST_MIN_PERCENTAGE_COMPLETE_MEAN = float(os.getenv("TEST_MIN_PERCENTAGE_COMPLETE_MEAN", -0.05))
 
 # After this number of consecutive timeouts, kill the submission:
 # this probably means the submission has crashed
@@ -661,6 +661,8 @@ class FlatlandRemoteEvaluationService:
         Handles a ENV_CREATE command from the client
         """
 
+        print(" -- [DEBUG] [env_create] EVAL DONE: ",self.evaluation_done)
+
         # Check if the previous episode was finished
         if not self.simulation_done and not self.evaluation_done:
             _command_response = self._error_template("CAN'T CREATE NEW ENV BEFORE PREVIOUS IS DONE")
@@ -678,6 +680,8 @@ class FlatlandRemoteEvaluationService:
         self.state_env_timed_out = False
 
         # Check if we have finished all the available envs
+        print(" -- [DEBUG] [env_create] SIM COUNT: ", self.simulation_count + 1, len(self.env_file_paths))
+        
         if self.simulation_count >= len(self.env_file_paths):
             self.evaluation_done = True
             # Hack - just ensure these are set
@@ -712,7 +716,7 @@ class FlatlandRemoteEvaluationService:
             """
 
             print("=" * 15)
-            print("Evaluating {} ({}/{})".format(test_env_file_path, self.simulation_count, len(self.env_file_paths)))
+            print("Evaluating {} ({}/{})".format(test_env_file_path, self.simulation_count+1, len(self.env_file_paths)))
 
             test_env_file_path = os.path.join(
                 self.test_env_folder,
@@ -725,6 +729,7 @@ class FlatlandRemoteEvaluationService:
             del self.env
 
             self.env, _env_dict = RailEnvPersister.load_new(test_env_file_path)
+            # distance map here?
 
             self.begin_simulation = time.time()
 
@@ -769,6 +774,7 @@ class FlatlandRemoteEvaluationService:
             _command_response['payload']['info'] = _info
             _command_response['payload']['random_seed'] = RANDOM_SEED
         else:
+            print(" -- [DEBUG] [env_create] return obs = False (END)")
             """
             All test env evaluations are complete
             """
diff --git a/setup.py b/setup.py
index cb09748e955972df03586fcf9ede33e7647cd79d..951597139909083748ad36810573ab0b2f3b47ed 100644
--- a/setup.py
+++ b/setup.py
@@ -80,6 +80,6 @@ setup(
     test_suite='tests',
     tests_require=test_requirements,
     url='https://gitlab.aicrowd.com/flatland/flatland',
-    version='2.2.2',
+    version='3.0.0',
     zip_safe=False,
 )