diff --git a/tictoc.py b/tictoc.py
new file mode 100644
index 0000000000000000000000000000000000000000..3881342b84f812e8c6007d410fefd0432715804d
--- /dev/null
+++ b/tictoc.py
@@ -0,0 +1,69 @@
+import time
+
+
+class TicToc:
+    """
+    Class to make the checking of how long times different parts of the program takes. Simply
+    write tic() where you want to start the timer and toc() when you want to stop timer. Can handle
+    multiple timers simultaneously by sending a key to tic and toc. Reset everything with reset()
+    and a specific key by providing thus key
+    """
+    def __init__(self):
+        self.logs = None
+        self._time_start = {"main": 0.0}
+        self.reset()
+
+    def __repr__(self):
+        """
+        How the class should be printed, will print like a normal dictionary
+        :return: Normal representation of a dictionary
+        """
+        return self.logs.__repr__()
+
+    def __getitem__(self, item):
+        """
+        Getter to retrieve a single timer
+        :param item: name of the log you want get
+        :return: Timer of the provided name
+        """
+        return self.logs.get(item)
+
+    def __iter__(self):
+        """
+        Iterator for the times
+        :return: iterator for the times that are logged
+        """
+        return self.logs.items().__iter__()
+
+    def tic(self, key="main"):
+        """
+        Start the timer for provided key
+        :param key: Name of the timer, used to save start time in a dict, defaults to "main"
+        :return: None
+        """
+        if key not in self.logs:
+            self.logs[key] = 0.0
+        self._time_start[key] = time.time()
+
+    def toc(self, key="main"):
+        """
+        Saves the time for provided key. Can be used multiple times from the same tic() then it will do addition
+        :param key: Name of the timer defaults to "main"
+        :return: None
+        """
+        try:
+            self.logs[key] += time.time() - self._time_start[key]
+
+        except KeyError:
+            "The provided key has not been initialized, need to run tic() before running toc()"
+
+    def reset(self, key=None):
+        """
+        Reset the log for the given key if the key exists. Leave key empty to reset all logs
+        :param key: what key you want to reset, defaults to None which will reset everything
+        :return: None
+        """
+        if key is None:
+            self.logs = {"main": 0.0}
+        elif key in self.logs:
+            self.logs[key] = 0.0
diff --git a/visualdebugger/README.md b/visualdebugger/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..294b42ceb0acd231d13fb887f3ef461d7bbc7b41
--- /dev/null
+++ b/visualdebugger/README.md
@@ -0,0 +1,119 @@
+# Visual Debugging
+These files provide some useful and hopefully easy to use tools to visualize what data you currently have. 
+
+The debuggers are using pygame to open a new window and draw shapes onto it. Feel free to modify the debugger in 
+order to suit your needs. 
+
+Also Note that since pygame only can have one window open at a time you are NOT able to run two different 
+types of debuggers simultaneous.
+
+## Getting started
+In the example below you can see how you get started with the visual debugger. In this example a debugger for a heatmap is set as the debugger.
+
+```python
+from library import *
+import numpy as np
+import visualdebugger.heat_map_debugger
+import visualdebugger.flow_debugger
+import visualdebugger.path_debugger
+
+
+class MyAgent(IDABot):
+    def __init__(self):
+        IDABot.__init__(self)
+
+        self.debugging = True
+        self.debugger = None
+        if self.debugging:
+            self.set_up_debugging()
+    
+    def set_up_debugging(self):
+        self.debugger = visualdebugger.heat_map_debugger.HeatMapDebugger()
+        self.debugger.set_color_map({(20, 20): (255, 255, 0)})
+        self.debugger.set_update_frequency(0.5)
+
+    def on_game_start(self):
+        IDABot.on_game_start(self)
+        self.debugger.on_start()
+
+    def on_step(self):
+        IDABot.on_step(self)
+        if self.debugging:
+            self.debugger.on_step(self.calculate_and_set_heatmap) # OBS function that is sent! NOT function call!
+
+    def calculate_and_set_heatmap(self):
+        my_units = self.get_my_units()
+        heat = np.zeros((self.my_bot.map_tools.height, self.my_bot.map_tools.width))
+        for unit in my_units:
+            heat[int(unit.position.y)][int(unit.position.x)] = 20
+        self.debugger.set_display_values(heat) # OBS important to set the values
+
+```
+
+1. You are probably best off having a boolean variable to make the switch between having the debugger on or off easy.
+
+2. Initialize the type of visual debugger you want to use by calling the constructor for that class. In the example 
+above this is done in the first line of “set_up_debugging()” and this function.
+
+3. The debugger must set up a window in order to have somewhere to draw onto. This is done in its on_start(). A good 
+place to call on this function is in on_game_start() just like in the example above.
+
+4. In order to update what the debugger shows you call its on_step function. This function will only do things as 
+often as the update frequency is set to (in the example above it is set to 0.5 Hz meaning once every other second). 
+So you can call this in the agent on_step() just like in the example above. This on step function can also take another 
+function and call on that function at that same frequency. It can be a good idea to have a function that calls the 
+.set_display_values() and have that being called this way.
+
+Note: The .set_display_values() takes different arguments based on what type of debugger you are using and if the 
+values ain’t correctly formatted a print will occur and say so. Please continue reading this in order to see how to 
+format the values or take a look directly in the source code.
+
+
+## Structure
+In this part you can see how to structure the parameters in order to show the values.
+
+### All VisualDebuggers:
+##### on_start(self)
+Sets up a pygame window that the on_step will draw onto.
+
+##### on_step(self, fun=None)
+Will keep track of the time that the last update of the window occured and if it should update it will do so. And will 
+also call on the function provided at the same time.
+
+##### set_update_frequency(self, new_frequency)
+Set how often you want the on_step to do things. The frequency is in Hertz (updates/second)
+
+##### set_display_values(self, *args)
+Set the values that should be displayed. The different types of debuggers have a bit different criterias for their 
+arguments so please check below or check the source code to get a better understanding.
+
+##### set_color_map(self, color_map)
+The Heatmap and Path debuggers make it easy to have different colors being displayed based on value. Use this function 
+to do so by inputting a color_map. The color_map should be a dictionary with tuples of length 2 as keys and length 3 
+as values. The key is the interval of which the color should represent. The interval will include the first value and 
+exclude the last value. And the three long tuples are (r, g, b) values. Note that if the colormap is not correctly 
+formatted this call won't do anything and print that there was something wrong. Intervals are not allowed to overlap!
+
+### FlowDebugger
+##### .set_display_values(self, map_values)
+map_values should be a 2d list or 2d numpy array where every row has the same length. The values have to be integers 
+or floats between 0 and 2*pi. The values represent the angle in radians and when run, the window will display arrows 
+pointing in those directions.
+
+### HeatMapDebugger
+##### .set_display_values(self, map_values)
+map_values should be a 2d list or 2d numpy array where every row has the same length. The values have to be integers 
+or floats. You are free to have these values represent whatever you want and based on the color_map you have set, the 
+color of each square will have that color.
+
+### PathDebugger
+##### .set_display_values(self, relevant_coordinates, map_size=(152, 176))
+This debugger can more or less do the exact same thing as the heatmap debugger but instead of having to provide an 
+entire 2d array you just need to provide the specific coordinates as the relevant_coordinates parameter. This should 
+be a dictionary with a tuple of coordinates (x, y) both integer values as key and the value you want that coordinate 
+to have is the value in the dictionary. You can also provide the size of the map you want as a second tuple. This size 
+defaults to (152, 176) since that is the size of the normal map used. But keep in mind that all the coordinates must 
+be in the range of the map_size!
+
+When using this debugger you can just like with the heatmap set the colormap in order to have different values for 
+different coordinates display different colors.
diff --git a/visualdebugger/flow_debugger.py b/visualdebugger/flow_debugger.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6c5ccf2f57e33005c5e7dca54126caf914629fa
--- /dev/null
+++ b/visualdebugger/flow_debugger.py
@@ -0,0 +1,83 @@
+import visualdebugger.visual_debugger
+import numpy as np
+import pygame
+import math
+
+
+class FlowDebugger(visualdebugger.visual_debugger.VisualDebugger):
+    def __init__(self):
+        super(FlowDebugger, self).__init__()
+        self.direction_map = []
+        self.arrows = []
+        self.arrow_color = (255, 0, 0)
+
+    def on_draw(self):
+        self.screen.fill(self.background_color)
+        for arrow in self.arrows:
+            self.screen.blit(pygame.transform.rotate(arrow[0], math.degrees(arrow[2])), arrow[1])
+
+        pygame.display.flip()
+        self.screen.fill(self.background_color)
+
+    def on_step(self, fun=None):
+        super().on_step(fun)
+
+        if self.should_update:
+            self.private_on_step()
+
+    def private_on_step(self):
+        if not self.screen:
+            self.on_start()
+        else:
+            pygame.event.pump()
+
+        self.arrows = []
+        # create squares and bind them to a value
+        for y_pos in range(len(self.direction_map)):
+            for x_pos in range(len(self.direction_map[y_pos])):
+                tile_width = int((self.screen.get_width() -
+                                  len(self.direction_map[y_pos]) * self.tile_margin) / len(self.direction_map[y_pos]))
+                tile_height = int((self.screen.get_height() -
+                                   len(self.direction_map) * self.tile_margin) / len(self.direction_map))
+
+                surface = pygame.Surface((tile_width, tile_height))
+
+                pygame.draw.polygon(surface, self.arrow_color, ((0+tile_width/6, tile_height/3),
+                                                                (0+tile_width/6, 2*tile_height/3),
+                                                                (2*tile_width/4, 2*tile_height/3),
+                                                                (2*tile_width/4, 5*tile_height/6),
+                                                                (5*tile_width/6, tile_height/2),
+                                                                (2*tile_width/4, 0+tile_height/6),
+                                                                (2*tile_width/4, tile_height/3))
+                                    )
+
+                dest_x = x_pos * (tile_width + self.tile_margin) + self.tile_margin
+                # y is flipped in order to match sc2 coords
+                dest_y = (len(self.direction_map) - y_pos - 1) * (tile_height + self.tile_margin) + self.tile_margin
+                position = (dest_x, dest_y)
+                self.arrows.append((surface, position, self.direction_map[y_pos][x_pos]))
+        self.on_draw()
+
+    def set_display_values(self, map_values):
+        """
+        Set what map that should be displayed, it has to be a 2d list
+        or a 2d numpy array. Where every row in the list has the same length.
+        The values has to be ints or floats between 0 and 2*pi
+        :param map_values: [[], []. [], ...]
+        :return: none, sets the values to display
+        """
+        try:
+            assert isinstance(map_values, (list, np.ndarray)) and len(map_values)
+            first_row = map_values[0]
+            for row in map_values:
+                assert isinstance(row, (list, np.ndarray)) and len(row)
+                assert(len(first_row) == len(row))
+                for column in row:
+                    assert isinstance(column, (int, float))
+                    assert 0 <= column <= 2*math.pi
+
+            self.direction_map = map_values
+
+        except AssertionError:
+            print("The map you set for debugger must be a list or numpy.array. It cant be empty and "
+                  "every row has to have the same length")
diff --git a/visualdebugger/heat_map_debugger.py b/visualdebugger/heat_map_debugger.py
new file mode 100644
index 0000000000000000000000000000000000000000..0b44532d6eb6d23e479f47e438979b66e040f9e1
--- /dev/null
+++ b/visualdebugger/heat_map_debugger.py
@@ -0,0 +1,115 @@
+import visualdebugger.visual_debugger
+import numpy as np
+import pygame
+
+
+class HeatMapDebugger(visualdebugger.visual_debugger.VisualDebugger):
+    def __init__(self):
+        super(HeatMapDebugger, self).__init__()
+        self.map_to_display = []
+        self.color_map = {}
+        self.squares = []
+
+    def on_draw(self):
+        self.screen.fill(self.background_color)
+        for square in self.squares:
+            pygame.draw.rect(self.screen, self.get_color_of_tile(square[1]), square[0])
+
+        pygame.display.flip()
+        self.screen.fill(self.background_color)
+
+    def on_step(self, fun=None):
+        super().on_step(fun)
+
+        if self.should_update:
+            self.private_on_step()
+
+    def private_on_step(self):
+        if not self.screen:
+            self.on_start()
+        else:
+            pygame.event.pump()
+
+        self.squares = []
+        # create squares and bind them to a value
+        for y_pos in range(len(self.map_to_display)):
+            for x_pos in range(len(self.map_to_display[y_pos])):
+                tile_val = self.map_to_display[y_pos][x_pos]
+
+                tile_width = int((self.screen.get_width() - len(self.map_to_display[y_pos]) * self.tile_margin)
+                                 / len(self.map_to_display[y_pos]))
+
+                tile_height = int((self.screen.get_height() - len(self.map_to_display) * self.tile_margin)
+                                  / len(self.map_to_display))
+
+                rect_pos_x = x_pos * (tile_width + self.tile_margin) + self.tile_margin
+                rect_pos_y = (len(self.map_to_display) - y_pos - 1) * \
+                             (tile_height + self.tile_margin) + self.tile_margin
+
+                self.squares.append((pygame.Rect(rect_pos_x, rect_pos_y, tile_width, tile_height),
+                                     tile_val))
+
+        self.on_draw()
+
+    def set_display_values(self, map_values):
+        """
+        Set what map that should be displayed, it has to be a 2d list
+        or a 2d numpy array. Where every row in the list has the same length
+        :param map_values: [[], []. [], ...]
+        :return:
+        """
+        try:
+            assert isinstance(map_values, (list, np.ndarray)) and len(map_values)
+            first_row = map_values[0]
+            for row in map_values:
+                assert isinstance(row, (list, np.ndarray)) and len(row)
+                assert(len(first_row) == len(row))
+                for number in row:
+                    assert isinstance(number, (int, float))
+            self.map_to_display = map_values
+
+        except AssertionError:
+            print("The map you set for debugger must be a list or numpy.array. It cant be empty and "
+                  "every row has to have the same length and every element must be a int or float")
+
+    def set_color_map(self, color_map):
+        """
+        Setter for the colormap. takes a dict with tuple of interval as key and rgb value it should represent as value.
+        interval is (include, exclude).
+
+        :param color_map: {interval(include, exclude): color (r, g, b)}.
+                          {(start of interval included, end of interval excluded): (r, g, b)}
+        :return: None, sets the colormap of the Heatmap
+        """
+        try:
+            assert isinstance(color_map, dict) and len(color_map)
+            occupied_intervals = []
+            for key in color_map.keys():
+                assert isinstance(key, tuple) and isinstance(color_map[key], tuple) and \
+                       len(key) == 2 and len(color_map[key]) == 3
+
+                assert key[0] <= key[1] and isinstance(key[0], (int, float)) \
+                       and isinstance(key[1], (int, float))
+
+                for interval in occupied_intervals:
+                    if not (key[1] <= interval[0] or key[0] >= interval[1]):
+                        print("interval: " + str(key) + " overlapped with: " + str(interval))
+                        raise ValueError
+
+                occupied_intervals.append(key)
+
+                for color_val in color_map[key]:
+                    assert 0 <= color_val <= 255
+
+            self.color_map = color_map
+
+        except AssertionError:
+            print("The colormap provided was not correctly formatted")
+        except ValueError:
+            print("The colormap provided had overlapping intervals")
+
+    def get_color_of_tile(self, tile_value):
+        for interval in self.color_map.keys():
+            if interval[0] <= tile_value < interval[1] or interval[0] == tile_value:
+                return self.color_map[interval]
+        return 0, 0, 0
diff --git a/visualdebugger/path_debugger.py b/visualdebugger/path_debugger.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab8c5204634bb0eb76beff145692936720ea3155
--- /dev/null
+++ b/visualdebugger/path_debugger.py
@@ -0,0 +1,122 @@
+import visualdebugger.visual_debugger
+import numpy as np
+import pygame
+
+
+class PathDebugger(visualdebugger.visual_debugger.VisualDebugger):
+    def __init__(self):
+        super(PathDebugger, self).__init__()
+        self.map_to_display = []
+        self.color_map = {}
+        self.squares = []
+
+    def on_draw(self):
+        self.screen.fill(self.background_color)
+        for square in self.squares:
+            pygame.draw.rect(self.screen, self.get_color_of_tile(square[1]), square[0])
+
+        pygame.display.flip()
+        self.screen.fill(self.background_color)
+
+    def on_step(self, fun=None):
+        super().on_step(fun)
+
+        if self.should_update:
+            self.private_on_step()
+
+    def private_on_step(self):
+        if not self.screen:
+            self.on_start()  # (super)
+        else:
+            pygame.event.pump()
+
+        self.squares = []
+        # create squares and bind them to a value
+        for y_pos in range(len(self.map_to_display)):
+            for x_pos in range(len(self.map_to_display[y_pos])):
+                tile_val = self.map_to_display[y_pos][x_pos]
+                tile_width = int((self.screen.get_width() - len(self.map_to_display[y_pos]) * self.tile_margin)
+                                 / len(self.map_to_display[y_pos]))
+                tile_height = int((self.screen.get_height() - len(self.map_to_display) * self.tile_margin)
+                                  / len(self.map_to_display))
+                rect_pos_x = x_pos * (tile_width + self.tile_margin) + self.tile_margin
+                rect_pos_y = (len(self.map_to_display) - y_pos - 1) * \
+                             (tile_height + self.tile_margin) + self.tile_margin
+
+                self.squares.append((pygame.Rect(rect_pos_x, rect_pos_y, tile_width, tile_height),
+                                     tile_val))
+        self.on_draw()
+
+    def set_display_values(self, relevant_coordinates, map_size=(152, 176)):
+        """
+        Set what map that should be displayed, it has to be a 2d list
+        or a 2d numpy array. Where every row in the list has the same length
+        :param relevant_coordinates: {(x, y) : value, (x, y): value, (x, y): value, ...}
+        :param map_size: (x:int, y:int)=(152, 176) size of map. relevant_coordinates.keys() must be in the range of
+                            these values
+        :return:
+        """
+        try:
+            assert isinstance(relevant_coordinates, dict) and len(relevant_coordinates)
+
+            assert (isinstance(map_size, tuple) and len(map_size) == 2)
+            assert isinstance(map_size[0], int) and isinstance(map_size[1], int) and \
+                   map_size[0] > 0 and map_size[1] > 0  # check that map size is valid
+
+            for coord in relevant_coordinates.keys():
+                assert isinstance(coord, tuple) and len(coord) == 2 and \
+                       isinstance(coord[0], int) and isinstance(coord[1], int)
+                assert (0 <= coord[0] < map_size[0] and 0 <= coord[1] < map_size[1])
+                assert isinstance(relevant_coordinates[coord], (int, float))
+
+            # set the map_to_display value of the relevant coords to the value provided. everything else zero.
+            self.map_to_display = np.zeros((map_size[1], map_size[0]))
+            for coord in relevant_coordinates.keys():
+                self.map_to_display[coord[1]][coord[0]] = relevant_coordinates[coord]
+
+        except AssertionError:
+            print("The relevant coordinates you set must be a dictionary with a tuple as key (x_pos, y_pos) \n"
+                  "and int or float as value. Coordinates must be in the range of the 0 to map_size-1 and \n"
+                  "the map_size must be a tuple with (width, height) map_size defaults to (152, 176)")
+
+    def set_color_map(self, color_map):
+        """
+        Setter for the colormap. takes a dict with tuple of interval as key and rgb value it should 
+        represent as value. interval is (include, exclude).
+
+        :param color_map: {interval(include, exclude): color (r, g, b)}.
+                            {(start of interval included, end of interval excluded): (r, g, b)}
+        :return: None, sets the colormap of the Heatmap
+        """
+        try:
+            assert isinstance(color_map, dict) and len(color_map)
+            occupied_intervals = []
+            for key in color_map.keys():
+                assert isinstance(key, tuple) and isinstance(color_map[key], tuple) and \
+                       len(key) == 2 and len(color_map[key]) == 3
+
+                assert isinstance(key[0], (int, float)) and isinstance(key[1], (int, float)) and key[0] <= key[1]
+
+                for interval in occupied_intervals:
+                    if not (key[1] <= interval[0] or key[0] >= interval[1]):
+                        print("interval: " + str(key) + " overlapped with: " + str(interval))
+                        raise ValueError
+
+                occupied_intervals.append(key)
+
+                for color_val in color_map[key]:
+                    assert isinstance(color_val, int)
+                    assert 0 <= color_val <= 255
+
+            self.color_map = color_map
+
+        except AssertionError:
+            print("The colormap provided was not correctly formatted")
+        except ValueError:
+            print("The colormap provided had overlapping intervals")
+
+    def get_color_of_tile(self, tile_value):
+        for interval in self.color_map.keys():
+            if interval[0] <= tile_value < interval[1] or interval[0] == tile_value:
+                return self.color_map[interval]
+        return 0, 0, 0
diff --git a/visualdebugger/visual_debugger.py b/visualdebugger/visual_debugger.py
new file mode 100644
index 0000000000000000000000000000000000000000..af93077f593f3fe41b1269c709c5ceef199f8921
--- /dev/null
+++ b/visualdebugger/visual_debugger.py
@@ -0,0 +1,39 @@
+import time
+import pygame
+
+
+class VisualDebugger:
+    """
+    Basic class for a visual debugger, easy to take this and make
+    a specific type of visual debugger a subclass of this.
+    Look at the other debuggers if you need guidance.
+    """
+    def __init__(self):
+        self.default_width = 152*5
+        self.default_height = 176*5
+        self.tile_margin = 1
+        self.background_color = (0, 0, 0)
+        self.screen = None
+        self.update_frequency = 0.5  # update frequency in Hz (updates per second)
+        self.last_update = 0
+        self.should_update = True
+
+    def on_start(self):
+        self.screen = pygame.display.set_mode((self.default_width, self.default_height))
+
+    def on_step(self, fun=None):
+        if time.time() - self.last_update > 1/self.update_frequency:  # updates if enough time has passed
+            if callable(fun):
+                fun()
+
+            self.last_update = time.time()
+            self.should_update = True
+
+        else:
+            self.should_update = False
+
+    def set_update_frequency(self, new_frequency):
+        self.update_frequency = new_frequency
+
+    def set_tile_margin(self, margin):
+        self.tile_margin = margin