diff --git a/Makefile b/Makefile
index c84991f6757fafa0ef6198205bcf92d886a0e060..35704d190e0f0fc1de0dd219f79bf462e7d8bda6 100644
--- a/Makefile
+++ b/Makefile
@@ -61,20 +61,10 @@ test-all: ## run tests on every Python version with tox
 	tox
 
 coverage: ## check code coverage quickly with the default Python
-	coverage run --source flatland -m pytest
-	coverage report -m
-	coverage html
-	$(BROWSER) htmlcov/index.html
+	python make_coverage.py
 
 docs: ## generate Sphinx HTML documentation, including API docs
-	rm -f docs/flatland*.rst
-	rm -f docs/modules.rst
-	sphinx-apidoc --force -a -e -o docs/ flatland -H "Flatland Reference"
-	$(MAKE) -C docs clean
-	cp *.md docs
-	$(MAKE) -C docs html
-	pydeps --no-config --noshow flatland -o docs/_build/html/flatland.svg
-	$(BROWSER) docs/_build/html/index.html
+	python make_docs.py
 
 servedocs: docs ## compile the docs watching for changes
 	watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .
diff --git a/benchmarks/benchmark_utils.py b/benchmarks/benchmark_utils.py
index 720590be315ca03abd07838c4475a5c586edf8dd..42792f98c427589e3b21d230b6451f85b984917e 100644
--- a/benchmarks/benchmark_utils.py
+++ b/benchmarks/benchmark_utils.py
@@ -12,7 +12,7 @@ def swap_attr(obj, attr, new_val):
             ...
 
         This will set obj.attr to 5 for the duration of the with: block,
-        restoring the old value at the end of the block. If `attr` doesn't
+        restoring the old value at the end of the block. If `attr` doesn`t
         exist on `obj`, it will be created and then deleted at the end of the
         block.
 
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 100644
index eb44e95ecbb9bc4079613db7f5d1e95ed4359691..0000000000000000000000000000000000000000
--- a/docs/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# Minimal makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-# TODO fix sphinx warnings instead of suppressing them...
-SPHINXOPTS    = -Q
-SPHINXBUILD   = python -msphinx
-SPHINXPROJ    = flatland
-SOURCEDIR     = .
-BUILDDIR      = _build
-
-# Put it first so that "make" without argument is like "make help".
-help:
-	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
-.PHONY: help Makefile
-
-# Catch-all target: route all unknown targets to Sphinx using the new
-# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile
-	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/changelog_index.rst b/docs/changelog_index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..081c500ffe5427b3dc9987c5fd0ed2ae6482ba6a
--- /dev/null
+++ b/docs/changelog_index.rst
@@ -0,0 +1,8 @@
+Changes
+=======
+
+.. toctree::
+   :maxdepth: 2
+
+   changelog.md
+   flatland_2.0.md
diff --git a/docs/conf.py b/docs/conf.py
index b0366ddb9abee1f32c9e8b17d7e5e78e2c2ad2c6..66f5183f192dc083f87fc9a0175c9f6fe733545e 100755
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -33,7 +33,7 @@ sys.path.insert(0, os.path.abspath('..'))
 
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['recommonmark', 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx']
+extensions = ['recommonmark', 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx', 'numpydoc']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -48,7 +48,6 @@ source_suffix = {
     '.md': 'markdown',
 }
 
-
 # The master toctree document.
 master_doc = 'index'
 
@@ -159,3 +158,6 @@ texinfo_documents = [
      'One line description of project.',
      'Miscellaneous'),
 ]
+
+# https://stackoverflow.com/questions/12206334/sphinx-autosummary-toctree-contains-reference-to-nonexisting-document-warnings
+numpydoc_show_class_members = False
diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst
index 0cfa43bb130880b84a71f2ce982cfefefb9deffd..8bde9adfa41089ab932a2d753befdc16b0a5d7ec 100644
--- a/docs/gettingstarted.rst
+++ b/docs/gettingstarted.rst
@@ -1,9 +1,9 @@
-=====
+===============
 Getting Started
-=====
+===============
 
 Overview
---------------
+--------
 
 Following are three short tutorials to help new users get acquainted with how
 to create RailEnvs, how to train simple DQN agents on them, and how to customize
@@ -17,7 +17,7 @@ To use flatland in a project:
 
 
 Part 1 : Basic Usage
---------------
+--------------------
 
 The basic usage of RailEnv environments consists in creating a RailEnv object
 endowed with a rail generator, that generates new rail networks on each reset,
@@ -120,7 +120,7 @@ The complete code for this part of the Getting Started guide can be found in
 
 
 Part 2 : Training a Simple an Agent on Flatland
---------------
+-----------------------------------------------
 This is a brief tutorial on how to train an agent on Flatland.
 Here we use a simple random agent to illustrate the process on how to interact with the environment.
 The corresponding code can be found in examples/training_example.py and in the baselines repository
@@ -153,7 +153,7 @@ The difficulty of a railway network depends on the dimensions (`width` x `height
 By varying the number of start and goal connections (nr_start_goal) and the number of extra railway elements added (nr_extra)
 the number of alternative paths of each agents can be modified. The more possible paths an agent has to reach its target the easier the task becomes.
 Here we don't specify any observation builder but rather use the standard tree observation. If you would like to use a custom obervation please follow
- the instructions in the next tutorial.
+the instructions in the next tutorial.
 Feel free to vary these parameters to see how your own agent holds up on different setting. The evalutation set of railway configurations will
 cover the whole spectrum from easy to complex tasks.
 
@@ -188,7 +188,7 @@ The environment returns an array of new observations, reward dictionary for all
 This information can be used to update the policy of your agent and if done['__all__'] == True the episode terminates.
 
 Part 3 : Customizing Observations and Level Generators
---------------
+------------------------------------------------------
 
 Example code for generating custom observations given a RailEnv and to generate
 random rail maps are available in examples/custom_observation_example.py and
@@ -257,6 +257,7 @@ random (but consistent) agents along with their targets and initial directions,
 given a rail map (GridTransitionMap object) and the desired number of agents:
 
 .. code-block:: python
+
     agents_position, agents_direction, agents_target = get_rnd_agents_pos_tgt_dir_on_rail(
         rail_map,
         num_agents)
diff --git a/docs/index.rst b/docs/index.rst
index f644f73e56b74ee5ea765e15d3ed5bef832614e9..ba35554ab50a17f118e744eefd3a77967828a17b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -10,13 +10,13 @@ Welcome to flatland's documentation!
    about_flatland
    gettingstarted
    intro_observationbuilder
-   specifications/specifications.md
+   intro_observation_actions
+   specifications_index
    modules
    FAQ
    localevaluation
    contributing
-   changelog.md
-   flatland_2.0.md
+   changelog_index
    authors
 
 
diff --git a/docs/observation_actions.rst b/docs/intro_observation_actions.rst
similarity index 100%
rename from docs/observation_actions.rst
rename to docs/intro_observation_actions.rst
diff --git a/docs/intro_observationbuilder.rst b/docs/intro_observationbuilder.rst
index 4386f9e07df07693d2a4e72fa1920e4275972c67..50d65fd4771e5a5362aa7250e6f50c9f884299f4 100644
--- a/docs/intro_observationbuilder.rst
+++ b/docs/intro_observationbuilder.rst
@@ -1,9 +1,9 @@
-=====
+==============================================================
 Getting Started with custom observations and custom predictors
-=====
+==============================================================
 
 Overview
---------------
+--------
 
 One of the main objectives of the Flatland-Challenge_ is to find a suitable observation (relevant features for the problem at hand) to solve the task. Therefore **Flatland** was built with as much flexibility as possible when it comes to building your custom observations: observations in Flatland environments are fully customizable.
 Whenever an environment needs to compute new observations for each agent, it queries an object derived from the :code:`ObservationBuilder` base class, which takes the current state of the environment and returns the desired observation.
@@ -12,7 +12,7 @@ Whenever an environment needs to compute new observations for each agent, it que
 .. _Flatland-Challenge: https://www.aicrowd.com/challenges/flatland-challenge
 
 Example 1 : Simple (but useless) observation
---------------------------------------------------------
+--------------------------------------------
 In this first example we implement all the functions necessary for the observation builder to be valid and work with **Flatland**.
 Custom observation builder objects need to derive from the `flatland.core.env_observation_builder.ObservationBuilder`_
 base class and must implement two methods, :code:`reset(self)` and :code:`get(self, handle)`.
@@ -300,9 +300,9 @@ When building your custom observation builder, you might want to aggregate and d
 Transitions maps
 ~~~~~~~~~~~~~~~~
 
-The transition maps build the base for all movement in the environment. They contain all the information about allowed transitions for the agent at any given position. Because railway movement is limited to the railway tracks, these are important features for any controller that want to interact with the environment. All functionality and features of a transition map can be found here_
+The transition maps build the base for all movement in the environment. They contain all the information about allowed transitions for the agent at any given position. Because railway movement is limited to the railway tracks, these are important features for any controller that want to interact with the environment. All functionality and features of a transition map can be found here_.
 
-.. _here:https://gitlab.aicrowd.com/flatland/flatland/blob/master/flatland/core/transition_map.py
+.. _here: https://gitlab.aicrowd.com/flatland/flatland/blob/master/flatland/core/transition_map.py
 
 **Get Transitions for cell**
 
@@ -312,7 +312,7 @@ To access the possible transitions at any given cell there are different possibi
 
 2. When more detailed information about the cell in general is necessary you can also get the full transitions of a cell by calling :code:`transition_int = env.rail.get_full_transitions(*position)`. This will return an :code:`int16` for the cell representing the allowed transitions. To understand the transitions returned it is best to represent it as a binary number :code:`bin(transition_int)`, where the bits have to following meaning: :code:`NN NE NS NW EN EE ES EW SN SE SS SW WN WE WS WW`. For example the binary code :code:`1000 0000 0010 0000`, represents a straigt where an agent facing north can transition north and an agent facing south can transition south and no other transitions are possible. To get a better feeling what the binary representations of the elements look like go to this Link_
 
-.. _Link:https://gitlab.aicrowd.com/flatland/flatland/blob/master/flatland/core/grid/rail_env_grid.py#L29
+.. _Link: https://gitlab.aicrowd.com/flatland/flatland/blob/master/flatland/core/grid/rail_env_grid.py#L29
 
 
 These two objects can be used for example to detect switches that are usable by other agents but not the observing agent itself. This can be an important feature when actions have to be taken in order to avoid conflicts.
@@ -350,9 +350,11 @@ All the agent in the initiated environment can be found in the :code:`env.agents
 Beyond the basic agent information we can also access more details about the agents type by looking at speed data:
 
 - Agent max speed :code:`agent.speed_data["speed"]` wich defines the traveling speed when the agent is moving.
-- Agent position fraction :code:``agent.speed_data["position_fraction"]` which is a number between 0 and 1 and indicates when the move to the next cell will occur. Each speed of an agent is 1 or a smaller fraction. At each :code:`env.step()` the agent moves at its fractional speed forwards and only changes to the next cell when the cumulated fractions are :code:`agent.speed_data["position_fraction"] >= 1.`
-- Agent can move at different speed which can be set up by modifying the agent.speed_data within the schedule_generator. For example refer this Link_
-.. _Link:https://gitlab.aicrowd.com/flatland/flatland/blob/master/flatland/envs/schedule_generators.py#L59
+- Agent position fraction :code:`agent.speed_data["position_fraction"]` which is a number between 0 and 1 and indicates when the move to the next cell will occur. Each speed of an agent is 1 or a smaller fraction. At each :code:`env.step()` the agent moves at its fractional speed forwards and only changes to the next cell when the cumulated fractions are :code:`agent.speed_data["position_fraction"] >= 1.`
+- Agent can move at different speed which can be set up by modifying the agent.speed_data within the schedule_generator. For example refer this _Link_Schedule_Generators.
+
+.. _Link_Schedule_Generators: https://gitlab.aicrowd.com/flatland/flatland/blob/master/flatland/envs/schedule_generators.py#L59
+
 **Agent malfunction information**
 
 Similar to the speed data you can also access individual data about the malfunctions of an agent. All data is available through :code:`agent.malfunction_data` with:
diff --git a/docs/localevaluation.rst b/docs/localevaluation.rst
index abfab39aaa33e836981d8e890bd1a9070d3dcae0..10f9001ba1722e93d7ecf6347fb6099d31f65ed7 100644
--- a/docs/localevaluation.rst
+++ b/docs/localevaluation.rst
@@ -1,22 +1,21 @@
-=====
+================
 Local Evaluation
-=====
+================
 
 This document explains you how to locally evaluate your submissions before making 
 an official submission to the competition.
 
 Requirements
---------------
+------------
 
 * **flatland-rl** : We expect that you have `flatland-rl` installed by following the instructions in  :doc:`installation`.
 
 * **redis** : Additionally you will also need to have  `redis installed <https://redis.io/topics/quickstart>`_ and **should have it running in the background.**
 
 Test Data
---------------
+---------
 
-* **test env data** : You can `download and untar the test-env-data <https://www.aicrowd.com/challenges/flatland-challenge/dataset_files>`_, 
-at a location of your choice, lets say `/path/to/test-env-data/`. After untarring the folder, the folder structure should look something like : 
+* **test env data** : You can `download and untar the test-env-data <https://www.aicrowd.com/challenges/flatland-challenge/dataset_files>`, at a location of your choice, lets say `/path/to/test-env-data/`. After untarring the folder, the folder structure should look something like:
 
 
 .. code-block:: console
@@ -48,11 +47,10 @@ Evaluation Service
     flatland-evaluator --tests /path/to/test-env-data/
 
 RemoteClient
-------------------
+------------
+
+* **run client** : Some `sample submission code can be found in the starter-kit <https://github.com/AIcrowd/flatland-challenge-starter-kit/>`_, but before you can run your code locally using `FlatlandRemoteClient`, you will have to set the `AICROWD_TESTS_FOLDER` environment variable to the location where you previous untarred the folder with `the test-env-data`:
 
-* **run client** : Some `sample submission code can be found in the starter-kit <https://github.com/AIcrowd/flatland-challenge-starter-kit/>`_, 
-but before you can run your code locally using `FlatlandRemoteClient`, you will have to set the `AICROWD_TESTS_FOLDER` environment variable to the location where you 
-previous untarred the folder with `the test-env-data`:
 
 .. code-block:: console
 
@@ -64,3 +62,4 @@ previous untarred the folder with `the test-env-data`:
 
     # and then finally run your code
     python run.py
+
diff --git a/docs/make.bat b/docs/make.bat
deleted file mode 100644
index 40b4f60ada7eb91f7153d03787084019bf219fb9..0000000000000000000000000000000000000000
--- a/docs/make.bat
+++ /dev/null
@@ -1,36 +0,0 @@
-@ECHO OFF
-
-pushd %~dp0
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
-	set SPHINXBUILD=python -msphinx
-)
-set SOURCEDIR=.
-set BUILDDIR=_build
-set SPHINXPROJ=flatland
-
-if "%1" == "" goto help
-
-%SPHINXBUILD% >NUL 2>NUL
-if errorlevel 9009 (
-	echo.
-	echo.The Sphinx module was not found. Make sure you have Sphinx installed,
-	echo.then set the SPHINXBUILD environment variable to point to the full
-	echo.path of the 'sphinx-build' executable. Alternatively you may add the
-	echo.Sphinx directory to PATH.
-	echo.
-	echo.If you don't have Sphinx installed, grab it from
-	echo.http://sphinx-doc.org/
-	exit /b 1
-)
-
-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
-goto end
-
-:help
-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
-
-:end
-popd
diff --git a/docs/specifications/rendering.md b/docs/specifications/rendering.md
index 46f53d0e2fb882fd39f039e9c5055f0aa3cbd2f5..baba1c06e16da99f20ee61e6feb6d031f0a415c2 100644
--- a/docs/specifications/rendering.md
+++ b/docs/specifications/rendering.md
@@ -4,8 +4,8 @@
 This doc specifies the software to meet the requirements in the Visualization requirements doc.
 
 ## References
-- [Visualization Requirements](Specifications/Visualization)
-- [Core Spec](Specifications/Core)
+- [Visualization Requirements](visualization)
+- [Core Spec](./core)
 
 ## Interfaces
 ### Interface with Environment Component
@@ -72,4 +72,4 @@ To-be-filled
 
 #### Overlay dynamic primitives over the background at each time step.
 
-No point trying to figure out changes. Need to explicitly draw every primitive anyways (that’s how these renders work).
\ No newline at end of file
+No point trying to figure out changes. Need to explicitly draw every primitive anyways (that’s how these renders work).
diff --git a/docs/specifications/specifications.md b/docs/specifications/specifications.md
index ec680147a4cbb2b9bf2962b7bbabd9d5312aecac..7d00259450cfe3217faa839df23cc00fd29ba3eb 100644
--- a/docs/specifications/specifications.md
+++ b/docs/specifications/specifications.md
@@ -11,7 +11,7 @@ In a humand-readable language, they provide
 ## Overview
 ![UML_flatland.png](img/UML_flatland.png)
 [Diagram Source](https://confluence.sbb.ch/x/pQfsSw)
-## [Core](core)
+
 
 
 ## Rail Generators and Schedule Generators
@@ -330,6 +330,3 @@ RailEnv.step()
                                                     self.get()
                                                     ...
 ```
-
-## [Rendering](rendering)
-## [Railway](railway)
diff --git a/docs/specifications_index.rst b/docs/specifications_index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..ce42dad5f3885bb425ed2cde88e0ea5dfb3eb358
--- /dev/null
+++ b/docs/specifications_index.rst
@@ -0,0 +1,12 @@
+Flatland Specs
+==============
+
+.. toctree::
+   :maxdepth: 2
+
+   specifications/specifications.md
+   specifications/core.md
+   specifications/railway.md
+   specifications/rendering.md
+   specifications/specifications.md
+   specifications/visualization.md
diff --git a/flatland/core/env.py b/flatland/core/env.py
index 1bc5b6f3eba4ee4713bd3c8d6b88440006c215a5..2dc983c5edd49e4ebb5033877b69f36f293141b2 100644
--- a/flatland/core/env.py
+++ b/flatland/core/env.py
@@ -15,6 +15,7 @@ class Environment:
 
     Agents are identified by agent ids (handles).
     Examples:
+
         >>> obs = env.reset()
         >>> print(obs)
         {
@@ -40,6 +41,7 @@ class Environment:
             "train_0": {},  # info for train_0
             "train_1": {},  # info for train_1
         }
+
     """
 
     def __init__(self):
@@ -51,7 +53,8 @@ class Environment:
         """
         Resets the env and returns observations from agents in the environment.
 
-        Returns:
+        Returns
+        -------
         obs : dict
             New observations for each agent.
         """
@@ -66,7 +69,7 @@ class Environment:
         The returns are dicts mapping from agent_id strings to values.
 
         Parameters
-        -------
+        ----------
         action_dict : dict
             Dictionary of actions to execute, indexed by agent id.
 
diff --git a/flatland/core/env_observation_builder.py b/flatland/core/env_observation_builder.py
index 4acdf16f292a1b3ef5b78620e588dea8c3ff27e3..ba79e7fc0e46d8182951b5a8e2520d7ffc9eacb0 100644
--- a/flatland/core/env_observation_builder.py
+++ b/flatland/core/env_observation_builder.py
@@ -2,10 +2,11 @@
 ObservationBuilder objects are objects that can be passed to environments designed for customizability.
 The ObservationBuilder-derived custom classes implement 2 functions, reset() and get() or get(handle).
 
-+ Reset() is called after each environment reset, to allow for pre-computing relevant data.
++ `reset()` is called after each environment reset, to allow for pre-computing relevant data.
+
++ `get()` is called whenever an observation has to be computed, potentially for each agent independently in case of \
+multi-agent environments.
 
-+ Get() is called whenever an observation has to be computed, potentially for each agent independently in
-case of multi-agent environments.
 """
 import numpy as np
 
@@ -14,7 +15,7 @@ class ObservationBuilder:
     """
     ObservationBuilder base class.
 
-    Derived objects must implement and `observation_space' attribute as a tuple with the dimensions of the returned
+    Derived objects must implement and `observation_space` attribute as a tuple with the dimensions of the returned
     observations.
     """
 
@@ -32,19 +33,19 @@ class ObservationBuilder:
 
     def get_many(self, handles=[]):
         """
-        Called whenever an observation has to be computed for the `env' environment, for each agent with handle
-        in the `handles' list.
+        Called whenever an observation has to be computed for the `env` environment, for each agent with handle
+        in the `handles` list.
 
         Parameters
-        -------
-        handles : list of handles (optional)
+        ----------
+        handles : list of handles, optional
             List with the handles of the agents for which to compute the observation vector.
 
         Returns
         -------
         function
             A dictionary of observation structures, specific to the corresponding environment, with handles from
-            `handles' as keys.
+            `handles` as keys.
         """
         observations = {}
         for h in handles:
@@ -53,12 +54,12 @@ class ObservationBuilder:
 
     def get(self, handle=0):
         """
-        Called whenever an observation has to be computed for the `env' environment, possibly
-        for each agent independently (agent id `handle').
+        Called whenever an observation has to be computed for the `env` environment, possibly
+        for each agent independently (agent id `handle`).
 
         Parameters
-        -------
-        handle : int (optional)
+        ----------
+        handle : int, optional
             Handle of the agent for which to compute the observation vector.
 
         Returns
diff --git a/flatland/core/env_prediction_builder.py b/flatland/core/env_prediction_builder.py
index 13eb38140fb25730d1817e2db7a17c350a2260c7..c1026fe02bfc2cfb30fd57ef570022ca3b15f6f0 100644
--- a/flatland/core/env_prediction_builder.py
+++ b/flatland/core/env_prediction_builder.py
@@ -3,9 +3,9 @@ PredictionBuilder objects are objects that can be passed to environments designe
 The PredictionBuilder-derived custom classes implement 2 functions, reset() and get([handle]).
 If predictions are not required in every step or not for all agents, then
 
-+ Reset() is called after each environment reset, to allow for pre-computing relevant data.
++ `reset()` is called after each environment reset, to allow for pre-computing relevant data.
 
-+ Get() is called whenever an step has to be computed, potentially for each agent independently in
++ `get()` is called whenever an step has to be computed, potentially for each agent independently in \
 case of multi-agent environments.
 """
 
@@ -33,11 +33,11 @@ class PredictionBuilder:
         Called whenever get_many in the observation build is called.
 
         Parameters
-        -------
+        ----------
         custom_args: dict
             Implementation-dependent custom arguments, see the sub-classes.
 
-        handle : int (optional)
+        handle : int, optional
             Handle of the agent for which to compute the observation vector.
 
         Returns
diff --git a/flatland/core/grid/grid4.py b/flatland/core/grid/grid4.py
index b4b5b17c9b1e6f5c7abd3c82a1fbf1e5ee96fcfe..da721dd99fbc0ea46124dcd036425df3206aa339 100644
--- a/flatland/core/grid/grid4.py
+++ b/flatland/core/grid/grid4.py
@@ -24,9 +24,9 @@ class Grid4Transitions(Transitions):
     """
     Grid4Transitions class derived from Transitions.
 
-    Special case of `Transitions' over a 2D-grid (FlatLand).
+    Special case of `Transitions` over a 2D-grid (FlatLand).
     Transitions are possible to neighboring cells on the grid if allowed.
-    GridTransitions keeps track of valid transitions supplied as `transitions'
+    GridTransitions keeps track of valid transitions supplied as `transitions`
     list, each represented as a bitmap of 16 bits.
 
     Whether a transition is allowed or not depends on which direction an agent
@@ -67,8 +67,8 @@ class Grid4Transitions(Transitions):
         """
         Get the 4 possible transitions ((N,E,S,W), 4 elements tuple
         if no diagonal transitions allowed) available for an agent oriented
-        in direction `orientation' and inside a cell with
-        transitions `cell_transition'.
+        in direction `orientation` and inside a cell with
+        transitions `cell_transition`.
 
         Parameters
         ----------
@@ -90,9 +90,9 @@ class Grid4Transitions(Transitions):
         """
         Set the possible transitions (e.g., (N,E,S,W), 4 elements tuple
         if no diagonal transitions allowed) available for an agent
-        oriented in direction `orientation' and inside a cell with transitions
-        `cell_transition'. A new `cell_transition' is returned with
-        the specified bits replaced by `new_transitions'.
+        oriented in direction `orientation` and inside a cell with transitions
+        `cell_transition'. A new `cell_transition` is returned with
+        the specified bits replaced by `new_transitions`.
 
         Parameters
         ----------
@@ -107,8 +107,8 @@ class Grid4Transitions(Transitions):
         -------
         int
             An updated bitmap that replaces the original transitions validity
-            of `cell_transition' with `new_transitions', for the appropriate
-            `orientation'.
+            of `cell_transition' with `new_transitions`, for the appropriate
+            `orientation`.
 
         """
         mask = (1 << ((4 - orientation) * 4)) - (1 << ((3 - orientation) * 4))
@@ -127,8 +127,8 @@ class Grid4Transitions(Transitions):
     def get_transition(self, cell_transition, orientation, direction):
         """
         Get the transition bit (1 value) that determines whether an agent
-        oriented in direction `orientation' and inside a cell with transitions
-        `cell_transition' can move to the cell in direction `direction'
+        oriented in direction `orientation` and inside a cell with transitions
+        `cell_transition' can move to the cell in direction `direction`
         relative to the current cell.
 
         Parameters
@@ -151,8 +151,8 @@ class Grid4Transitions(Transitions):
     def set_transition(self, cell_transition, orientation, direction, new_transition, remove_deadends=False):
         """
         Set the transition bit (1 value) that determines whether an agent
-        oriented in direction `orientation' and inside a cell with transitions
-        `cell_transition' can move to the cell in direction `direction'
+        oriented in direction `orientation` and inside a cell with transitions
+        `cell_transition' can move to the cell in direction `direction`
         relative to the current cell.
 
         Parameters
@@ -171,8 +171,8 @@ class Grid4Transitions(Transitions):
         -------
         int
             An updated bitmap that replaces the original transitions validity
-            of `cell_transition' with `new_transitions', for the appropriate
-            `orientation'.
+            of `cell_transition' with `new_transitions`, for the appropriate
+            `orientation`.
 
         """
         if new_transition:
@@ -196,7 +196,7 @@ class Grid4Transitions(Transitions):
             16 bits used to encode the valid transitions for a cell.
         rotation : int
             Angle by which to clock-wise rotate the transition bits in
-            `cell_transition' by. I.e., rotation={0, 90, 180, 270} degrees.
+            `cell_transition` by. I.e., rotation={0, 90, 180, 270} degrees.
 
         Returns
         -------
diff --git a/flatland/core/grid/grid8.py b/flatland/core/grid/grid8.py
index 2ba379a5ecb4099de999905d34daf91ccccac640..a4dcc3d215a3ff0fd699924e489d2fb17191a37c 100644
--- a/flatland/core/grid/grid8.py
+++ b/flatland/core/grid/grid8.py
@@ -20,9 +20,9 @@ class Grid8Transitions(Transitions):
     """
     Grid8Transitions class derived from Transitions.
 
-    Special case of `Transitions' over a 2D-grid (FlatLand).
+    Special case of `Transitions` over a 2D-grid (FlatLand).
     Transitions are possible to neighboring cells on the grid if allowed.
-    GridTransitions keeps track of valid transitions supplied as `transitions'
+    GridTransitions keeps track of valid transitions supplied as `transitions`
     list, each represented as a bitmap of 64 bits.
 
     0=North, 1=North-East, etc.
@@ -82,8 +82,8 @@ class Grid8Transitions(Transitions):
         -------
         int
             An updated bitmap that replaces the original transitions validity
-            of `cell_transition' with `new_transitions', for the appropriate
-            `orientation'.
+            of `cell_transition' with `new_transitions`, for the appropriate
+            `orientation`.
 
         """
         mask = (1 << ((8 - orientation) * 8)) - (1 << ((7 - orientation) * 8))
@@ -106,8 +106,8 @@ class Grid8Transitions(Transitions):
     def get_transition(self, cell_transition, orientation, direction):
         """
         Get the transition bit (1 value) that determines whether an agent
-        oriented in direction `orientation' and inside a cell with transitions
-        `cell_transition' can move to the cell in direction `direction'
+        oriented in direction `orientation` and inside a cell with transitions
+        `cell_transition' can move to the cell in direction `direction`
         relative to the current cell.
 
         Parameters
@@ -131,8 +131,8 @@ class Grid8Transitions(Transitions):
 
         """
         Set the transition bit (1 value) that determines whether an agent
-        oriented in direction `orientation' and inside a cell with transitions
-        `cell_transition' can move to the cell in direction `direction'
+        oriented in direction `orientation` and inside a cell with transitions
+        `cell_transition' can move to the cell in direction `direction`
         relative to the current cell.
 
         Parameters
@@ -150,8 +150,8 @@ class Grid8Transitions(Transitions):
         -------
         int
             An updated bitmap that replaces the original transitions validity
-            of `cell_transition' with `new_transitions', for the appropriate
-            `orientation'.
+            of `cell_transition' with `new_transitions`, for the appropriate
+            `orientation`.
 
         """
         if new_transition:
@@ -172,7 +172,7 @@ class Grid8Transitions(Transitions):
             64 bits used to encode the valid transitions for a cell.
         rotation : int
             Angle by which to clock-wise rotate the transition bits in
-            `cell_transition' by. I.e., rotation={0, 45, 90, 135, 180,
+            `cell_transition` by. I.e., rotation={0, 45, 90, 135, 180,
             225, 270, 315} degrees.
 
         Returns
diff --git a/flatland/core/grid/grid_utils.py b/flatland/core/grid/grid_utils.py
index f51d285947ae175692ca70e1f03d08b8a22a5a22..09e664f2c85f5919f8769653d91ccd7f6e621ec2 100644
--- a/flatland/core/grid/grid_utils.py
+++ b/flatland/core/grid/grid_utils.py
@@ -1,25 +1,27 @@
 import numpy as np
 
 
-def position_to_coordinate(depth, positions):
-    """Converts coordinates to positions:
-         [ (0,0) (0,1) ..  (0,w-1)
-           (1,0) (1,1)     (1,w-1)
-           ...
-           (d-1,0) (d-1,1)     (d-1,w-1)
-          ]
+def position_to_coordinate(depth: int, positions):
+    """Converts coordinates to positions::
+
+        [ (0,0) (0,1) ..  (0,w-1)
+          (1,0) (1,1)     (1,w-1)
+            ...
+          (d-1,0) (d-1,1)     (d-1,w-1)
+        ]
 
          -->
 
-         [ 0      d    ..  (w-1)*d
-           1      d+1
-           ...
-           d-1    2d-1     w*d-1
-         ]
+        [ 0      d    ..  (w-1)*d
+          1      d+1
+          ...
+          d-1    2d-1     w*d-1
+        ]
 
-    :param depth:
-    :param positions:
-    :return:
+    Parameters
+    ----------
+    depth : int
+    positions : List[Tuple[int,int]]
     """
     coords = ()
     for p in positions:
@@ -29,7 +31,8 @@ def position_to_coordinate(depth, positions):
 
 def coordinate_to_position(depth, coords):
     """
-    Converts positions to coordinates:
+    Converts positions to coordinates::
+
          [ 0      d    ..  (w-1)*d
            1      d+1
            ...
diff --git a/flatland/core/grid/rail_env_grid.py b/flatland/core/grid/rail_env_grid.py
index db09fbd57b18d203c956742d4711973c986ca452..ffc0e5bfe9dc992052356ed45dc7fe6cf98adfee 100644
--- a/flatland/core/grid/rail_env_grid.py
+++ b/flatland/core/grid/rail_env_grid.py
@@ -4,11 +4,9 @@ from flatland.utils.ordered_set import OrderedSet
 
 class RailEnvTransitions(Grid4Transitions):
     """
-    Special case of `GridTransitions' over a 2D-grid, with a pre-defined set
+    Special case of `GridTransitions` over a 2D-grid, with a pre-defined set
     of transitions mimicking the types of real Swiss rail connections.
 
-    --------------------------------------------------------------------------
-
     As no diagonal transitions are allowed in the RailEnv environment, the
     possible transitions for RailEnv from a cell to its neighboring ones
     are represented over 16 bits.
diff --git a/flatland/core/transition_map.py b/flatland/core/transition_map.py
index 105f1c90bc7201b4d8c9b17e184fc6d56ffb02b2..fc5bb1d3514b55d805a8323385749cd7349f4c17 100644
--- a/flatland/core/transition_map.py
+++ b/flatland/core/transition_map.py
@@ -24,7 +24,7 @@ class TransitionMap:
     def get_transitions(self, cell_id):
         """
         Return a tuple of transitions available in a cell specified by
-        `cell_id' (e.g., a tuple of size of the maximum number of transitions,
+        `cell_id` (e.g., a tuple of size of the maximum number of transitions,
         with values 0 or 1, or potentially in between,
         for stochastic transitions).
 
@@ -44,8 +44,8 @@ class TransitionMap:
 
     def set_transitions(self, cell_id, new_transitions):
         """
-        Replaces the available transitions in cell `cell_id' with the tuple
-        `new_transitions'. `new_transitions' must have
+        Replaces the available transitions in cell `cell_id` with the tuple
+        `new_transitions'. `new_transitions` must have
         one element for each possible transition.
 
         Parameters
@@ -61,8 +61,8 @@ class TransitionMap:
 
     def get_transition(self, cell_id, transition_index):
         """
-        Return the status of whether an agent in cell `cell_id' can perform a
-        movement along transition `transition_index (e.g., the NESW direction
+        Return the status of whether an agent in cell `cell_id` can perform a
+        movement along transition `transition_index` (e.g., the NESW direction
         of movement, for agents on a grid).
 
         Parameters
@@ -86,8 +86,8 @@ class TransitionMap:
 
     def set_transition(self, cell_id, transition_index, new_transition):
         """
-        Replaces the validity of transition to `transition_index' in cell
-        `cell_id' with the new `new_transition'.
+        Replaces the validity of transition to `transition_index` in cell
+        `cell_id' with the new `new_transition`.
 
 
         Parameters
@@ -157,7 +157,7 @@ class GridTransitionMap(TransitionMap):
     def get_transitions(self, row, column, orientation):
         """
         Return a tuple of transitions available in a cell specified by
-        `cell_id' (e.g., a tuple of size of the maximum number of transitions,
+        `cell_id` (e.g., a tuple of size of the maximum number of transitions,
         with values 0 or 1, or potentially in between,
         for stochastic transitions).
 
@@ -179,8 +179,8 @@ class GridTransitionMap(TransitionMap):
 
     def set_transitions(self, cell_id, new_transitions):
         """
-        Replaces the available transitions in cell `cell_id' with the tuple
-        `new_transitions'. `new_transitions' must have
+        Replaces the available transitions in cell `cell_id` with the tuple
+        `new_transitions'. `new_transitions` must have
         one element for each possible transition.
 
         Parameters
@@ -205,8 +205,8 @@ class GridTransitionMap(TransitionMap):
 
     def get_transition(self, cell_id, transition_index):
         """
-        Return the status of whether an agent in cell `cell_id' can perform a
-        movement along transition `transition_index (e.g., the NESW direction
+        Return the status of whether an agent in cell `cell_id` can perform a
+        movement along transition `transition_index` (e.g., the NESW direction
         of movement, for agents on a grid).
 
         Parameters
@@ -233,8 +233,8 @@ class GridTransitionMap(TransitionMap):
 
     def set_transition(self, cell_id, transition_index, new_transition, remove_deadends=False):
         """
-        Replaces the validity of transition to `transition_index' in cell
-        `cell_id' with the new `new_transition'.
+        Replaces the validity of transition to `transition_index` in cell
+        `cell_id' with the new `new_transition`.
 
 
         Parameters
@@ -262,7 +262,7 @@ class GridTransitionMap(TransitionMap):
 
     def save_transition_map(self, filename):
         """
-        Save the transitions grid as `filename', in npy format.
+        Save the transitions grid as `filename`, in npy format.
 
         Parameters
         ----------
@@ -274,9 +274,9 @@ class GridTransitionMap(TransitionMap):
 
     def load_transition_map(self, package, resource):
         """
-        Load the transitions grid from `filename' (npy format).
+        Load the transitions grid from `filename` (npy format).
         The load function only updates the transitions grid, and possibly width and height, but the object has to be
-        initialized with the correct `transitions' object anyway.
+        initialized with the correct `transitions` object anyway.
 
         Parameters
         ----------
@@ -286,7 +286,7 @@ class GridTransitionMap(TransitionMap):
             Name of the file from which to load the transitions grid within the package.
         override_gridsize : bool
             If override_gridsize=True, the width and height of the GridTransitionMap object are replaced with the size
-            of the map loaded from `filename'. If override_gridsize=False, the transitions grid is either cropped (if
+            of the map loaded from `filename`. If override_gridsize=False, the transitions grid is either cropped (if
             the grid size is larger than (height,width) ) or padded with zeros (if the grid size is smaller than
             (height,width) )
 
@@ -375,8 +375,7 @@ class GridTransitionMap(TransitionMap):
         """
         Check validity of cell at rcPos = tuple(row, column)
         Checks that:
-        - surrounding cells have inbound transitions for all the
-            outbound transitions of this cell.
+        - surrounding cells have inbound transitions for all the outbound transitions of this cell.
 
         These are NOT checked - see transition.is_valid:
         - all transitions have the mirror transitions (N->E <=> W->S)
@@ -427,8 +426,7 @@ class GridTransitionMap(TransitionMap):
         """
         Check validity of cell at rcPos = tuple(row, column)
         Checks that:
-        - surrounding cells have inbound transitions for all the
-            outbound transitions of this cell.
+        - surrounding cells have inbound transitions for all the outbound transitions of this cell.
 
         These are NOT checked - see transition.is_valid:
         - all transitions have the mirror transitions (N->E <=> W->S)
diff --git a/flatland/core/transitions.py b/flatland/core/transitions.py
index 5049c23bff3667a08375fee270a8867ca013c467..995c2d4e7a911c4e01b64b0673c2bdf1420d324c 100644
--- a/flatland/core/transitions.py
+++ b/flatland/core/transitions.py
@@ -12,7 +12,7 @@ class Transitions:
 
     Generic class that implements checks to control whether a
     certain transition is allowed (agent facing a direction
-    `orientation' and moving into direction `orientation')
+    `orientation' and moving into direction `orientation`)
     """
 
     def get_type(self):
@@ -21,7 +21,7 @@ class Transitions:
     def get_transitions(self, cell_transition, orientation):
         """
         Return a tuple of transitions available in a cell specified by
-        `cell_transition' for an agent facing direction `orientation'
+        `cell_transition' for an agent facing direction `orientation`
         (e.g., a tuple of size of the maximum number of transitions,
         with values 0 or 1, or potentially in between,
         for stochastic transitions).
@@ -45,9 +45,9 @@ class Transitions:
 
     def set_transitions(self, cell_transition, orientation, new_transitions):
         """
-        Return a `cell_transition' specification where the transitions
-        available for an agent facing direction `orientation' are replaced
-        with the tuple `new_transitions'. `new_orientations' must have
+        Return a `cell_transition` specification where the transitions
+        available for an agent facing direction `orientation` are replaced
+        with the tuple `new_transitions'. `new_orientations` must have
         one element for each possible transition.
 
         Parameters
@@ -65,8 +65,8 @@ class Transitions:
         -------
         [cell-content]
             An updated class-specific object that replaces the original
-            transitions validity of `cell_transition' with `new_transitions',
-            for the appropriate `orientation'.
+            transitions validity of `cell_transition' with `new_transitions`,
+            for the appropriate `orientation`.
 
         """
         raise NotImplementedError()
@@ -74,8 +74,8 @@ class Transitions:
     def get_transition(self, cell_transition, orientation, direction):
         """
         Return the status of whether an agent oriented in directions
-        `orientation' and inside a cell with transitions `cell_transition'
-        can move to the cell in direction `direction' relative
+        `orientation' and inside a cell with transitions `cell_transition`
+        can move to the cell in direction `direction` relative
         to the current cell.
 
         Parameters
@@ -101,11 +101,11 @@ class Transitions:
     def set_transition(self, cell_transition, orientation, direction,
                        new_transition):
         """
-        Return a `cell_transition' specification where the status of
-        whether an agent oriented in direction `orientation' and inside
-        a cell with transitions `cell_transition' can move to the cell
-        in direction `direction' relative to the current cell is set
-        to `new_transition'.
+        Return a `cell_transition` specification where the status of
+        whether an agent oriented in direction `orientation` and inside
+        a cell with transitions `cell_transition` can move to the cell
+        in direction `direction` relative to the current cell is set
+        to `new_transition`.
 
         Parameters
         ----------
@@ -125,8 +125,8 @@ class Transitions:
         -------
         [cell-content]
             An updated class-specific object that replaces the original
-            transitions validity of `cell_transition' with `new_transitions',
-            for the appropriate `orientation' to `direction'.
+            transitions validity of `cell_transition' with `new_transitions`,
+            for the appropriate `orientation' to `direction`.
 
         """
         raise NotImplementedError()
diff --git a/flatland/envs/observations.py b/flatland/envs/observations.py
index 85cd5fdc798fde4f1a5f2b75edeefce2dfa2104a..2a1c52207630a72f2749ba22ab7c46241839d4ab 100644
--- a/flatland/envs/observations.py
+++ b/flatland/envs/observations.py
@@ -6,7 +6,6 @@ import pprint
 import numpy as np
 
 from flatland.core.env_observation_builder import ObservationBuilder
-from flatland.core.grid.grid4 import Grid4TransitionsEnum
 from flatland.core.grid.grid4_utils import get_new_position
 from flatland.core.grid.grid_utils import coordinate_to_position
 from flatland.utils.ordered_set import OrderedSet
@@ -46,8 +45,8 @@ class TreeObsForRailEnv(ObservationBuilder):
 
     def get_many(self, handles=None):
         """
-        Called whenever an observation has to be computed for the `env' environment, for each agent with handle
-        in the `handles' list.
+        Called whenever an observation has to be computed for the `env` environment, for each agent with handle
+        in the `handles` list.
         """
 
         if handles is None:
@@ -75,15 +74,17 @@ class TreeObsForRailEnv(ObservationBuilder):
 
     def get(self, handle):
         """
-        Computes the current observation for agent `handle' in env
+        Computes the current observation for agent `handle` in env
 
         The observation vector is composed of 4 sequential parts, corresponding to data from the up to 4 possible
         movements in a RailEnv (up to because only a subset of possible transitions are allowed in RailEnv).
         The possible movements are sorted relative to the current orientation of the agent, rather than NESW as for
-        the transitions. The order is:
+        the transitions. The order is::
+
             [data from 'left'] + [data from 'forward'] + [data from 'right'] + [data from 'back']
 
-        Each branch data is organized as:
+        Each branch data is organized as::
+
             [root node information] +
             [recursive branch data from 'left'] +
             [... from 'forward'] +
@@ -92,39 +93,50 @@ class TreeObsForRailEnv(ObservationBuilder):
 
         Each node information is composed of 9 features:
 
-        #1: if own target lies on the explored branch the current distance from the agent in number of cells is stored.
+        #1:
+            if own target lies on the explored branch the current distance from the agent in number of cells is stored.
 
-        #2: if another agents target is detected the distance in number of cells from the agents current location
+        #2:
+            if another agents target is detected the distance in number of cells from the agents current location\
             is stored
 
-        #3: if another agent is detected the distance in number of cells from current agent position is stored.
+        #3:
+            if another agent is detected the distance in number of cells from current agent position is stored.
 
-        #4: possible conflict detected
-            tot_dist = Other agent predicts to pass along this cell at the same time as the agent, we store the
+        #4:
+            possible conflict detected
+            tot_dist = Other agent predicts to pass along this cell at the same time as the agent, we store the \
              distance in number of cells from current agent position
 
             0 = No other agent reserve the same cell at similar time
 
-        #5: if an not usable switch (for agent) is detected we store the distance.
+        #5:
+            if an not usable switch (for agent) is detected we store the distance.
 
-        #6: This feature stores the distance in number of cells to the next branching  (current node)
+        #6:
+            This feature stores the distance in number of cells to the next branching  (current node)
 
-        #7: minimum distance from node to the agent's target given the direction of the agent if this path is chosen
+        #7:
+            minimum distance from node to the agent's target given the direction of the agent if this path is chosen
 
-        #8: agent in the same direction
-            n = number of agents present same direction
+        #8:
+            agent in the same direction
+            n = number of agents present same direction \
                 (possible future use: number of other agents in the same direction in this branch)
             0 = no agent present same direction
 
-        #9: agent in the opposite direction
-            n = number of agents present other direction than myself (so conflict)
+        #9:
+            agent in the opposite direction
+            n = number of agents present other direction than myself (so conflict) \
                 (possible future use: number of other agents in other direction in this branch, ie. number of conflicts)
             0 = no agent present other direction than myself
 
-        #10: malfunctioning/blokcing agents
+        #10:
+            malfunctioning/blokcing agents
             n = number of time steps the oberved agent remains blocked
 
-        #11: slowest observed speed of an agent in same direction
+        #11:
+            slowest observed speed of an agent in same direction
             1 if no agent is observed
 
             min_fractional speed otherwise
@@ -336,7 +348,7 @@ class TreeObsForRailEnv(ObservationBuilder):
                     last_is_dead_end = True
 
                 if not last_is_dead_end:
-                    # Keep walking through the tree along `direction'
+                    # Keep walking through the tree along `direction`
                     exploring = True
                     # convert one-hot encoding to 0,1,2,3
                     direction = np.argmax(cell_transitions)
@@ -355,7 +367,7 @@ class TreeObsForRailEnv(ObservationBuilder):
                 last_is_terminal = True
                 break
 
-        # `position' is either a terminal node or a switch
+        # `position` is either a terminal node or a switch
 
         # #############################
         # #############################
@@ -489,10 +501,10 @@ class GlobalObsForRailEnv(ObservationBuilder):
     Gives a global observation of the entire rail environment.
     The observation is composed of the following elements:
 
-        - transition map array with dimensions (env.height, env.width, 16),
+        - transition map array with dimensions (env.height, env.width, 16),\
           assuming 16 bits encoding of transitions.
 
-        - Two 2D arrays (map_height, map_width, 2) containing respectively the position of the given agent
+        - Two 2D arrays (map_height, map_width, 2) containing respectively the position of the given agent\
          target and the positions of the other agents targets.
 
         - A 3D array (map_height, map_width, 4) wtih
@@ -546,14 +558,14 @@ class LocalObsForRailEnv(ObservationBuilder):
     Gives a local observation of the rail environment around the agent.
     The observation is composed of the following elements:
 
-        - transition map array of the local environment around the given agent,
-          with dimensions (view_height,2*view_width+1, 16),
+        - transition map array of the local environment around the given agent, \
+          with dimensions (view_height,2*view_width+1, 16), \
           assuming 16 bits encoding of transitions.
 
-        - Two 2D arrays (view_height,2*view_width+1, 2) containing respectively,
+        - Two 2D arrays (view_height,2*view_width+1, 2) containing respectively, \
         if they are in the agent's vision range, its target position, the positions of the other targets.
 
-        - A 2D array (view_height,2*view_width+1, 4) containing the one hot encoding of directions
+        - A 2D array (view_height,2*view_width+1, 4) containing the one hot encoding of directions \
           of the other agents at their position coordinates, if they are in the agent's vision range.
 
         - A 4 elements array with one hot encoding of the direction.
@@ -561,6 +573,8 @@ class LocalObsForRailEnv(ObservationBuilder):
     Use the parameters view_width and view_height to define the rectangular view of the agent.
     The center parameters moves the agent along the height axis of this rectangle. If it is 0 the agent only has
     observation in front of it.
+
+    .. deprecated:: 2.0.0
     """
 
     def __init__(self, view_width, view_height, center):
@@ -625,8 +639,8 @@ class LocalObsForRailEnv(ObservationBuilder):
 
     def get_many(self, handles=None):
         """
-        Called whenever an observation has to be computed for the `env' environment, for each agent with handle
-        in the `handles' list.
+        Called whenever an observation has to be computed for the `env` environment, for each agent with handle
+        in the `handles` list.
         """
 
         observations = {}
diff --git a/flatland/envs/predictions.py b/flatland/envs/predictions.py
index 7f03b5be43d98ba3b4d87d933c267457fd133ddd..ccf4b967c3eabe2ff85dc4084720aa8fc3ca9628 100644
--- a/flatland/envs/predictions.py
+++ b/flatland/envs/predictions.py
@@ -23,8 +23,10 @@ class DummyPredictorForRailEnv(PredictionBuilder):
         Called whenever get_many in the observation build is called.
 
         Parameters
-        -------
-        handle : int (optional)
+        ----------
+        custom_args: dict
+            Not used in this dummy implementation.
+        handle : int, optional
             Handle of the agent for which to compute the observation vector.
 
         Returns
@@ -95,8 +97,10 @@ class ShortestPathPredictorForRailEnv(PredictionBuilder):
         Requires distance_map to extract the shortest path.
 
         Parameters
-        -------
-        handle : int (optional)
+        ----------
+        custom_args: dict
+            - distance_map : dict
+        handle : int, optional
             Handle of the agent for which to compute the observation vector.
 
         Returns
diff --git a/flatland/envs/rail_generators.py b/flatland/envs/rail_generators.py
index e5f0a8e8dcbe81660727e4eb04f5d4a0f636b5d4..f2dc5c46dfdf11c31b865483f20dfbc19f4964e6 100644
--- a/flatland/envs/rail_generators.py
+++ b/flatland/envs/rail_generators.py
@@ -38,8 +38,10 @@ def complex_rail_generator(nr_start_goal=1,
                            max_dist=99999,
                            seed=0) -> RailGenerator:
     """
+    complex_rail_generator
+
     Parameters
-    -------
+    ----------
     width : int
         The width (number of cells) of the grid to generate.
     height : int
@@ -165,7 +167,7 @@ def rail_from_manual_specifications_generator(rail_spec):
     transitions specifications.
 
     Parameters
-    -------
+    ----------
     rail_spec : list of list of tuples
         List (rows) of lists (columns) of tuples, each specifying a rail_spec_of_cell for
         the RailEnv environment as (cell_type, rotation), with rotation being
@@ -207,7 +209,7 @@ def rail_from_file(filename) -> RailGenerator:
     Utility to load pickle file
 
     Parameters
-    -------
+    ----------
     filename : Pickle file generated by env.save() or editor
 
     Returns
@@ -241,14 +243,14 @@ def rail_from_grid_transition_map(rail_map) -> RailGenerator:
     16-bit transitions specifications.
 
     Parameters
-    -------
+    ----------
     rail_map : GridTransitionMap object
         GridTransitionMap object to return when the generator is called.
 
     Returns
     -------
     function
-        Generator function that always returns the given `rail_map' object.
+        Generator function that always returns the given `rail_map` object.
     """
 
     def generator(width: int, height: int, num_agents: int, num_resets: int = 0) -> RailGeneratorProduct:
@@ -261,13 +263,13 @@ def random_rail_generator(cell_type_relative_proportion=[1.0] * 11) -> RailGener
     """
     Dummy random level generator:
     - fill in cells at random in [width-2, height-2]
-    - keep filling cells in among the unfilled ones, such that all transitions
-      are legit;  if no cell can be filled in without violating some
-      transitions, pick one among those that can satisfy most transitions
-      (1,2,3 or 4), and delete (+mark to be re-filled) the cells that were
+    - keep filling cells in among the unfilled ones, such that all transitions\
+      are legit;  if no cell can be filled in without violating some\
+      transitions, pick one among those that can satisfy most transitions\
+      (1,2,3 or 4), and delete (+mark to be re-filled) the cells that were\
       incompatible.
-    - keep trying for a total number of insertions
-      (e.g., (W-2)*(H-2)*MAX_REPETITIONS ); if no solution is found, empty the
+    - keep trying for a total number of insertions\
+      (e.g., (W-2)*(H-2)*MAX_REPETITIONS ); if no solution is found, empty the\
       board and try again from scratch.
     - finally pad the border of the map with dead-ends to avoid border issues.
 
@@ -277,7 +279,7 @@ def random_rail_generator(cell_type_relative_proportion=[1.0] * 11) -> RailGener
     found to turn most un-genereatable levels into valid ones.
 
     Parameters
-    -------
+    ----------
     width : int
         The width (number of cells) of the grid to generate.
     height : int
@@ -527,11 +529,12 @@ def random_rail_generator(cell_type_relative_proportion=[1.0] * 11) -> RailGener
 
 
 def sparse_rail_generator(num_cities=5, num_intersections=4, num_trainstations=2, min_node_dist=20, node_radius=2,
-                          num_neighb=3, grid_mode=False, enhance_intersection=False, seed=0):
+                          num_neighb=3, grid_mode=False, enhance_intersection=False, seed=0) -> RailGenerator:
     """
     This is a level generator which generates complex sparse rail configurations
 
     :param num_cities: Number of city node (can hold trainstations)
+    :type num_cities: int
     :param num_intersections: Number of intersection that city nodes can connect to
     :param num_trainstations: Total number of trainstations in env
     :param min_node_dist: Minimal distance between nodes
@@ -540,13 +543,10 @@ def sparse_rail_generator(num_cities=5, num_intersections=4, num_trainstations=2
     :param grid_mode: True -> NOdes evenly distirbuted in env, False-> Random distribution of nodes
     :param enhance_intersection: True -> Extra rail elements added at intersections
     :param seed: Random Seed
-    :return:
-        -------
-    numpy.ndarray of type numpy.uint16
-        The matrix with the correct 16-bit bitmaps for each cell.
+    :return: numpy.ndarray of type numpy.uint16 -- The matrix with the correct 16-bit bitmaps for each cell.
     """
 
-    def generator(width, height, num_agents, num_resets=0):
+    def generator(width, height, num_agents, num_resets=0) -> RailGeneratorProduct:
 
         if num_agents > num_trainstations:
             num_agents = num_trainstations
diff --git a/flatland/envs/schedule_generators.py b/flatland/envs/schedule_generators.py
index 9b90e7c1c8d8e8c8ee09ff2412bd8fda56f57d10..467e4a7fe2e00a3c6dc1720382ca6188b6affd7f 100644
--- a/flatland/envs/schedule_generators.py
+++ b/flatland/envs/schedule_generators.py
@@ -17,7 +17,7 @@ ScheduleGenerator = Callable[[GridTransitionMap, int, Optional[Any]], ScheduleGe
 def speed_initialization_helper(nb_agents: int, speed_ratio_map: Mapping[float, float] = None) -> List[float]:
     """
     Parameters
-    -------
+    ----------
     nb_agents : int
         The number of agents to generate a speed for
     speed_ratio_map : Mapping[float,float]
@@ -115,22 +115,19 @@ def sparse_schedule_generator(speed_ratio_map: Mapping[float, float] = None) ->
     return generator
 
 
-def random_schedule_generator(speed_ratio_map: Mapping[float, float] = None) -> ScheduleGenerator:
+def random_schedule_generator(speed_ratio_map: Optional[Mapping[float, float]] = None) -> ScheduleGenerator:
     """
-    Given a `rail' GridTransitionMap, return a random placement of agents (initial position, direction and target).
+    Given a `rail` GridTransitionMap, return a random placement of agents (initial position, direction and target).
 
     Parameters
-    -------
-        rail : GridTransitionMap
-            The railway to place agents on.
-        num_agents : int
-            The number of agents to generate a speed for
-        speed_ratio_map : Mapping[float,float]
-            A map of speeds mappint to their ratio of appearance. The ratios must sum up to 1.
+    ----------
+        speed_ratio_map : Optional[Mapping[float, float]]
+            A map of speeds mapping to their ratio of appearance. The ratios must sum up to 1.
+
     Returns
     -------
         Tuple[List[Tuple[int,int]], List[Tuple[int,int]], List[Tuple[int,int]], List[float]]
-        initial positions, directions, targets speeds
+            initial positions, directions, targets speeds
     """
 
     def generator(rail: GridTransitionMap, num_agents: int, hints: Any = None) -> ScheduleGeneratorProduct:
@@ -213,7 +210,7 @@ def schedule_from_file(filename) -> ScheduleGenerator:
     Utility to load pickle file
 
     Parameters
-    -------
+    ----------
     input_file : Pickle file generated by env.save() or editor
 
     Returns
diff --git a/flatland/utils/rendertools.py b/flatland/utils/rendertools.py
index 802b361b623cdaea08271f5748ac86194056bdf2..99958bf38449ef8eb58c519990f1975106409c4e 100644
--- a/flatland/utils/rendertools.py
+++ b/flatland/utils/rendertools.py
@@ -560,7 +560,7 @@ class RenderTool(object):
                 position = agent.position
                 direction = agent.direction
                 for possible_directions in range(4):
-                    # Is a transition along movement `desired_movement_from_new_cell' to the current cell possible?
+                    # Is a transition along movement `desired_movement_from_new_cell` to the current cell possible?
                     isValid = env.rail.get_transition((*agent.position, agent.direction), possible_directions)
                     if isValid:
                         direction = possible_directions
diff --git a/make_docs.py b/make_docs.py
index be36a7bb7caed714445399b73f958ab42172242c..0a805e591647162e2757b60a7bcd9f75f4d1d0b9 100644
--- a/make_docs.py
+++ b/make_docs.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
-
+import glob
 import os
+import shutil
 import subprocess
 import webbrowser
 from urllib.request import pathname2url
@@ -18,16 +19,26 @@ def remove_exists(filename):
 
 
 # clean docs config and html files, and rebuild everything
-remove_exists('docs/flatland.rst')
+# wildcards do not work under Windows
+for file in glob.glob(r'./docs/flatland*.rst'):
+    remove_exists(file)
 remove_exists('docs/modules.rst')
 
-subprocess.call(['sphinx-apidoc', '-o', 'docs/', 'flatland'])
+# copy md files from root folder into docs folder
+for file in glob.glob(r'./*.md'):
+    print(file)
+    shutil.copy(file, 'docs/')
+
+subprocess.call(['sphinx-apidoc', '--force', '-a', '-e', '-o', 'docs/', 'flatland', '-H', 'Flatland Reference'])
 
-os.environ["SPHINXPROJ"] = "flatland"
+os.environ["SPHINXPROJ"] = "Flatland"
 os.chdir('docs')
 subprocess.call(['python', '-msphinx', '-M', 'clean', '.', '_build'])
 # TODO fix sphinx warnings instead of suppressing them...
-subprocess.call(['python', '-msphinx', '-M', 'html', '.', '_build', '-Q'])
-subprocess.call(['python', '-mpydeps', '../flatland', '-o', '_build/html/flatland.svg', '--no-config', '--noshow'])
+subprocess.call(['python', '-msphinx', '-M', 'html', '.', '_build'])
+# subprocess.call(['python', '-msphinx', '-M', 'html', '.', '_build', '-Q'])
+
+# we do not currrently use pydeps, commented out https://gitlab.aicrowd.com/flatland/flatland/issues/149
+# subprocess.call(['python', '-mpydeps', '../flatland', '-o', '_build/html/flatland.svg', '--no-config', '--noshow'])
 
 browser('_build/html/index.html')
diff --git a/requirements_continuous_integration.txt b/requirements_continuous_integration.txt
index db4885e736a6225c46624f3b20266c403d935626..0054fec1724765b8ffa8be620c5d4c1ac4cfd6b3 100644
--- a/requirements_continuous_integration.txt
+++ b/requirements_continuous_integration.txt
@@ -4,8 +4,10 @@ wheel>=0.32.1
 watchdog>=0.9.0
 benchmarker>=4.0.1
 coverage>=4.5.1
-Sphinx>=1.8.1
+# pin sphinx to <2.0 because of https://github.com/readthedocs/sphinx_rtd_theme/issues/746
+Sphinx>=1.8.1,<2.0
 sphinx-rtd-theme>=0.4.3
+numpydoc>=0.9.1
 docutils>=0.15.2
 flake8>=3.7.7
 flake8-eradicate>=0.2.0
diff --git a/tests/test_flatland_envs_observations.py b/tests/test_flatland_envs_observations.py
index 46000de429092d3fe4effe87382d1e12bc2c3401..d2663916a17a70597d10e489da7aead4f8932dc4 100644
--- a/tests/test_flatland_envs_observations.py
+++ b/tests/test_flatland_envs_observations.py
@@ -59,7 +59,7 @@ def _step_along_shortest_path(env, obs_builder, rail):
 
                 # Check all possible transitions in new_cell
                 for agent_orientation in range(4):
-                    # Is a transition along movement `entry_direction' to the neighbour possible?
+                    # Is a transition along movement `entry_direction` to the neighbour possible?
                     is_valid = obs_builder.env.rail.get_transition((neighbour[0], neighbour[1], agent_orientation),
                                                                    desired_movement_from_new_cell)
                     if is_valid:
diff --git a/tox.ini b/tox.ini
index 0b445e902454376b22ef95cd31d11800f659f3a8..b7a359b43c79cbb5d274755b35fd9f6a7873daff 100644
--- a/tox.ini
+++ b/tox.ini
@@ -21,8 +21,6 @@ commands =
     flake8 flatland tests examples benchmarks
 
 [testenv:docs]
-; TODO https://gitlab.aicrowd.com/flatland/flatland/issues/33 docs requires make installed, therefore exclude Windows
-platform = linux|linux2|darwin
 ; use python3.6 because of incompatibility under Windows of the pycairo installed through conda for py37
 basepython = python3.6
 whitelist_externals = make
@@ -46,8 +44,6 @@ commands =
     make docs
 
 [testenv:coverage]
-; TODO https://gitlab.aicrowd.com/flatland/flatland/issues/33 coverage requires make, therefore exclude Windows
-platform = linux|linux2|darwin
 ; use python3.6 because of incompatibility under Windows of the pycairo installed through conda for py37
 basepython = python3.6
 whitelist_externals = make
@@ -68,7 +64,7 @@ deps =
     -r{toxinidir}/requirements_continuous_integration.txt
 changedir = {toxinidir}
 commands =
-    make coverage
+    python make_coverage.py
 
 [testenv:benchmarks]
 ; use python3.6 because of incompatibility under Windows of the pycairo installed through conda for py37