diff --git a/overcooked_simulator/__init__.py b/overcooked_simulator/__init__.py
index c5d7d61bd0acf0412b5affe0069c97bbab98bf2e..05cb843178a2897e655d7e11e372f81e7d57d43f 100644
--- a/overcooked_simulator/__init__.py
+++ b/overcooked_simulator/__init__.py
@@ -32,6 +32,8 @@ python overcooked_simulator/main.py
 ## Direct integration into your code.
 Initialize an environment....
 
+**TODO** JSON State description.
+
 
 # Citation
 
diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py
index 2cbbeb4d048a7d113c784ea1792103cdda1bdba1..b20ff3f07d12126d84e2150adec4e19b2e61a606 100644
--- a/overcooked_simulator/counters.py
+++ b/overcooked_simulator/counters.py
@@ -19,6 +19,7 @@ Stove:
 """
 from __future__ import annotations
 
+import dataclasses
 import logging
 from collections import deque
 from datetime import datetime, timedelta
@@ -272,6 +273,18 @@ class Dispenser(Counter):
         return Item(**kwargs)
 
 
+@dataclasses.dataclass
+class PlateConfig:
+    """Configure the initial and behavior of the plates in the environment."""
+
+    clean_plates: int = 0
+    """clean plates at the start."""
+    dirty_plates: int = 3
+    """dirty plates at the start."""
+    plate_delay: list[int, int] = dataclasses.field(default_factory=lambda: [5, 10])
+    """The uniform sampling range for the plate delay between serving and return."""
+
+
 class PlateDispenser(Counter):
     """At the moment, one and only one plate dispenser must exist in an environment, because only at one place the dirty
     plates should arrive.
@@ -289,14 +302,13 @@ class PlateDispenser(Counter):
     """
 
     def __init__(
-        self, pos, dispensing, plate_config, plate_transitions, **kwargs
+        self, pos, dispensing, plate_config: PlateConfig, plate_transitions, **kwargs
     ) -> None:
         super().__init__(pos, **kwargs)
         self.dispensing = dispensing
         self.occupied_by = deque()
         self.out_of_kitchen_timer = []
-        self.plate_config = {"plate_delay": [5, 10]}
-        self.plate_config.update(plate_config)
+        self.plate_config = plate_config
         self.next_plate_time = datetime.max
         self.plate_transitions = plate_transitions
         self.setup_plates()
@@ -325,8 +337,8 @@ class PlateDispenser(Counter):
         # not perfect identical to datetime.now but based on framerate enough.
         time_plate_to_add = env_time + timedelta(
             seconds=np.random.uniform(
-                low=self.plate_config["plate_delay"][0],
-                high=self.plate_config["plate_delay"][1],
+                low=self.plate_config.plate_delay[0],
+                high=self.plate_config.plate_delay[1],
             )
         )
         log.debug(f"New plate out of kitchen until {time_plate_to_add}")
@@ -336,15 +348,17 @@ class PlateDispenser(Counter):
 
     def setup_plates(self):
         """Create plates based on the config. Clean and dirty ones."""
-        if "dirty_plates" in self.plate_config:
+        if self.plate_config.dirty_plates > 0:
+            log.info(f"Setup {self.plate_config.dirty_plates} dirty plates.")
             self.occupied_by.extend(
-                [self.create_item() for _ in range(self.plate_config["dirty_plates"])]
+                [self.create_item() for _ in range(self.plate_config.dirty_plates)]
             )
-        if "clean_plates" in self.plate_config:
+        if self.plate_config.clean_plates > 0:
+            log.info(f"Setup {self.plate_config.dirty_plates} clean plates.")
             self.occupied_by.extend(
                 [
                     self.create_item(clean=True)
-                    for _ in range(self.plate_config["clean_plates"])
+                    for _ in range(self.plate_config.clean_plates)
                 ]
             )
 
diff --git a/overcooked_simulator/gui_2d_vis/__init__.py b/overcooked_simulator/gui_2d_vis/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3afb0b56bf80f430bf71e2d165e46f4e396f1fe7 100644
--- a/overcooked_simulator/gui_2d_vis/__init__.py
+++ b/overcooked_simulator/gui_2d_vis/__init__.py
@@ -0,0 +1,26 @@
+"""
+2D visualization of the overcooked simulator.
+
+You can select the layout and start an environment:
+
+You can play the overcooked simulator. You can quit the application in the top right or end the level in the bottom right.
+![start screen](images/overcooked-start-screen.png)
+
+The orders are pictured in the top, the current score in the bottom left and the remaining time in the bottom.
+![level screen](images/overcooked-level-screen.png)
+
+The final screen after ending a level shows the score:
+![end screen](images/overcooked-end-screen.png)
+
+The keys for the control of the players are:
+
+Player 1:
+- Movement: `W`, `A`, `S`, `D`,
+- Pickup: `E`
+- Interact: `F`
+
+Player 2:
+- Movement: `⬆`, `⬅`, `⬇`, `➡` (arrow keys)
+- Pickup: `I`
+- Interact: `SPACE`
+"""
diff --git a/overcooked_simulator/gui_2d_vis/images/overcooked-end-screen.png b/overcooked_simulator/gui_2d_vis/images/overcooked-end-screen.png
new file mode 100644
index 0000000000000000000000000000000000000000..d678687d61277930d839882aa5f6956caeb5e9a6
Binary files /dev/null and b/overcooked_simulator/gui_2d_vis/images/overcooked-end-screen.png differ
diff --git a/overcooked_simulator/gui_2d_vis/images/overcooked-level-screen.png b/overcooked_simulator/gui_2d_vis/images/overcooked-level-screen.png
new file mode 100644
index 0000000000000000000000000000000000000000..0f2cc384aacabcd80d3b88542fd9a3345506b35d
Binary files /dev/null and b/overcooked_simulator/gui_2d_vis/images/overcooked-level-screen.png differ
diff --git a/overcooked_simulator/gui_2d_vis/images/overcooked-start-screen.png b/overcooked_simulator/gui_2d_vis/images/overcooked-start-screen.png
new file mode 100644
index 0000000000000000000000000000000000000000..420d1eedb6cf57a493aba7dbabe7e3ba80ecb1b4
Binary files /dev/null and b/overcooked_simulator/gui_2d_vis/images/overcooked-start-screen.png differ
diff --git a/overcooked_simulator/gui_2d_vis/overcooked_gui.py b/overcooked_simulator/gui_2d_vis/overcooked_gui.py
index 0e7db7ccea58611bfa917562639d4b9dfcae5c68..7c3f4d0ca7bd781373c4d3d990a0064aaab8e45a 100644
--- a/overcooked_simulator/gui_2d_vis/overcooked_gui.py
+++ b/overcooked_simulator/gui_2d_vis/overcooked_gui.py
@@ -23,7 +23,11 @@ from overcooked_simulator.game_items import (
 from overcooked_simulator.gui_2d_vis.game_colors import BLUE
 from overcooked_simulator.gui_2d_vis.game_colors import colors, Color
 from overcooked_simulator.order import Order
-from overcooked_simulator.overcooked_environment import Action
+from overcooked_simulator.overcooked_environment import (
+    Action,
+    ActionType,
+    InterActionData,
+)
 from overcooked_simulator.simulation_runner import Simulator
 
 USE_PLAYER_COOK_SPRITES = True
@@ -224,7 +228,7 @@ class PyGameGUI:
                 if np.linalg.norm(move_vec) != 0:
                     move_vec = move_vec / np.linalg.norm(move_vec)
 
-                action = Action(key_set.name, "movement", move_vec)
+                action = Action(key_set.name, ActionType.MOVEMENT, move_vec)
                 self.send_action(action)
 
     def handle_key_event(self, event):
@@ -237,15 +241,19 @@ class PyGameGUI:
         """
         for key_set in self.player_key_sets:
             if event.key == key_set.pickup_key and event.type == pygame.KEYDOWN:
-                action = Action(key_set.name, "pickup", "pickup")
+                action = Action(key_set.name, ActionType.PICKUP, "pickup")
                 self.send_action(action)
 
             if event.key == key_set.interact_key:
                 if event.type == pygame.KEYDOWN:
-                    action = Action(key_set.name, "interact", "keydown")
+                    action = Action(
+                        key_set.name, ActionType.INTERACT, InterActionData.START
+                    )
                     self.send_action(action)
                 elif event.type == pygame.KEYUP:
-                    action = Action(key_set.name, "interact", "keyup")
+                    action = Action(
+                        key_set.name, ActionType.INTERACT, InterActionData.STOP
+                    )
                     self.send_action(action)
 
     def draw_background(self):
diff --git a/overcooked_simulator/order.py b/overcooked_simulator/order.py
index 54c7ef1e7a8b9948df220fe28fa17376c992e7cf..ae3447aa830f7ff4e5f71970f8cc90d2ffb266e9 100644
--- a/overcooked_simulator/order.py
+++ b/overcooked_simulator/order.py
@@ -1,4 +1,22 @@
-""""""
+"""
+You can configure the order creation/generation via the `environment_config.yml`.
+
+It is very configurable by letting you reference own Python classes and functions.
+
+```yaml
+orders:
+  serving_not_ordered_meals: null
+  order_gen_class:  !!python/name:overcooked_simulator.order.RandomOrderGeneration ''
+  order_gen_kwargs:
+    ...
+```
+
+For the `serving_not_ordered_meals` is a function expected. It received a meal as an argument and should return a
+tuple of a bool and the score. If the bool is true, the score will be added to the score. Otherwise, it will not
+accept the meal for serving.
+
+The `order_gen_class` should be a child of the `OrderGeneration` class. The `order_gen_kwargs` depend then on your
+class referenced."""
 from __future__ import annotations
 
 import dataclasses
@@ -370,7 +388,7 @@ class OrderAndScoreManager:
         self.order_gen: OrderGeneration = order_config["order_gen_class"](
             available_meals=available_meals, kwargs=order_config["order_gen_kwargs"]
         )
-        self.kwargs_for_func = order_config["kwargs"]
+        self.kwargs_for_func = order_config["order_gen_kwargs"]
         self.serving_not_ordered_meals = order_config["serving_not_ordered_meals"]
         self.available_meals = available_meals
         self.open_orders: Deque[Order] = deque()
diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py
index f4bd59de451d5f02b9d1f99ab24c13490f7b7b40..9ec02b2bfa990b885344f2f8db8ea66c6378cedf 100644
--- a/overcooked_simulator/overcooked_environment.py
+++ b/overcooked_simulator/overcooked_environment.py
@@ -1,10 +1,13 @@
 from __future__ import annotations
 
+import dataclasses
 import logging
 import random
 from datetime import timedelta
+from enum import Enum
 from pathlib import Path
 from threading import Lock
+from typing import Literal
 
 import numpy as np
 import numpy.typing as npt
@@ -21,6 +24,7 @@ from overcooked_simulator.counters import (
     Sink,
     PlateDispenser,
     SinkAddon,
+    PlateConfig,
 )
 from overcooked_simulator.game_items import (
     ItemInfo,
@@ -28,27 +32,45 @@ from overcooked_simulator.game_items import (
     CookingEquipment,
 )
 from overcooked_simulator.order import OrderAndScoreManager
-from overcooked_simulator.player import Player
+from overcooked_simulator.player import Player, PlayerConfig
 from overcooked_simulator.utils import create_init_env_time
 
 log = logging.getLogger(__name__)
 
 
+class ActionType(Enum):
+    """The 3 different types of valid actions. They can be extended via the `Action.action_data` attribute."""
+
+    MOVEMENT = "movement"
+    """move the agent."""
+    PICKUP = "pickup"
+    """interaction type 1, e.g., for pickup or drop off."""
+    INTERACT = "interact"
+    """interaction type 2, e.g., for progressing. Start and stop interaction via `keydown` and `keyup` actions."""
+
+
+class InterActionData(Enum):
+    """The data for the interaction action: `ActionType.MOVEMENT`."""
+
+    START = "keydown"
+    "start an interaction."
+    STOP = "keyup"
+    "stop an interaction without moving away."
+
+
+@dataclasses.dataclass
 class Action:
     """Action class, specifies player, action type and action itself."""
 
-    def __init__(self, player, act_type, action):
-        self.player = player
-        self.act_type = act_type
-        assert self.act_type in [
-            "movement",
-            "pickup",
-            "interact",
-        ], "Unknown action type"
-        self.action = action
+    player: str
+    """Id of the player."""
+    action_type: ActionType
+    """Type of the action to perform. Defines what action data is valid."""
+    action_data: npt.NDArray[float] | InterActionData | Literal["pickup"]
+    """Data for the action, e.g., movement vector or start and stop interaction."""
 
     def __repr__(self):
-        return f"Action({self.player},{self.act_type},{self.action})"
+        return f"Action({self.player},{self.action_type.value},{self.action_data})"
 
 
 class Environment:
@@ -123,9 +145,13 @@ class Environment:
                 plate_transitions=plate_transitions,
                 pos=pos,
                 dispensing=self.item_info["Plate"],
-                plate_config=self.environment_config["plates"]
-                if "plates" in self.environment_config
-                else {},
+                plate_config=PlateConfig(
+                    **(
+                        self.environment_config["plates"]
+                        if "plates" in self.environment_config
+                        else {}
+                    )
+                ),
             ),
             "N": lambda pos: Dispenser(pos, self.item_info["Onion"]),  # N for oNioN
             "_": "Free",
@@ -187,6 +213,8 @@ class Environment:
         self.init_counters()
 
         self.env_time = create_init_env_time()
+        """the internal time of the environment. An environment starts always with the time from 
+        `create_init_env_time`."""
         self.order_and_score.create_init_orders(self.env_time)
         self.beginning_time = self.env_time
         self.env_time_end = self.env_time + timedelta(
@@ -195,6 +223,9 @@ class Environment:
         log.debug(f"End time: {self.env_time_end}")
 
     def get_env_time(self):
+        """the internal time of the environment. An environment starts always with the time from `create_init_env_time`.
+
+        Utility method to pass a reference to the serving window."""
         return self.env_time
 
     @property
@@ -202,6 +233,7 @@ class Environment:
         return self.env_time >= self.env_time_end
 
     def load_item_info(self) -> dict[str, ItemInfo]:
+        """Load `item_info.yml`, create ItemInfo classes and replace equipment strings with item infos."""
         with open(self.item_info_path, "r") as file:
             item_lookup = yaml.safe_load(file)
         for item_name in item_lookup:
@@ -213,6 +245,7 @@ class Environment:
         return item_lookup
 
     def validate_item_info(self):
+        """TODO"""
         pass
         # infos = {t: [] for t in ItemType}
         # graph = nx.DiGraph()
@@ -325,22 +358,22 @@ class Environment:
         assert action.player in self.players.keys(), "Unknown player."
         player = self.players[action.player]
 
-        if action.act_type == "movement":
+        if action.action_type == ActionType.MOVEMENT:
             with self.lock:
-                self.perform_movement(player, action.action)
+                self.perform_movement(player, action.action_data)
 
         else:
             counter = self.get_facing_counter(player)
             if player.can_reach(counter):
-                if action.act_type == "pickup":
+                if action.action_type == ActionType.PICKUP:
                     with self.lock:
                         player.pick_action(counter)
 
-                elif action.act_type == "interact":
-                    if action.action == "keydown":
+                elif action.action_type == ActionType.INTERACT:
+                    if action.action_data == InterActionData.START:
                         player.perform_interact_hold_start(counter)
                         player.last_interacted_counter = counter
-            if action.action == "keyup":
+            if action.action_data == InterActionData.STOP:
                 if player.last_interacted_counter:
                     with self.lock:
                         player.perform_interact_hold_stop(
@@ -464,7 +497,7 @@ class Environment:
         other_players = filter(lambda p: p.name != player.name, self.players.values())
 
         def collide(p):
-            return np.linalg.norm(player.pos - p.pos) <= (player.radius) + (p.radius)
+            return np.linalg.norm(player.pos - p.pos) <= player.radius + p.radius
 
         return list(filter(collide, other_players))
 
@@ -482,7 +515,7 @@ class Environment:
         other_players = filter(lambda p: p.name != player.name, self.players.values())
 
         def collide(p):
-            return np.linalg.norm(player.pos - p.pos) <= ((player.radius) + (p.radius))
+            return np.linalg.norm(player.pos - p.pos) <= (player.radius + p.radius)
 
         return any(map(collide, other_players))
 
@@ -502,7 +535,8 @@ class Environment:
             )
         )
 
-    def detect_collision_player_counter(self, player: Player, counter: Counter):
+    @staticmethod
+    def detect_collision_player_counter(player: Player, counter: Counter):
         """Checks if the player and counter collide (overlap).
         A counter is modelled as a rectangle (square actually), a player is modelled as a circle.
         The distance of the player position (circle center) and the counter rectangle is calculated, if it is
@@ -520,12 +554,26 @@ class Environment:
         dx = max(np.abs(cx - counter.pos[0]) - 1 / 2, 0)
         dy = max(np.abs(cy - counter.pos[1]) - 1 / 2, 0)
         distance = np.linalg.norm([dx, dy])
-        return distance < (player.radius)
+        return distance < player.radius
 
     def add_player(self, player_name: str, pos: npt.NDArray = None):
+        """Add a player to the environment.
+
+        Args:
+            player_name: The id/name of the player to reference actions and in the state.
+            pos: The optional init position of the player.
+        """
         log.debug(f"Add player {player_name} to the game")
         player = Player(
-            player_name, player_config=self.environment_config["player_config"], pos=pos
+            player_name,
+            player_config=PlayerConfig(
+                **(
+                    self.environment_config["player_config"]
+                    if "player_config" in self.environment_config
+                    else {}
+                )
+            ),
+            pos=pos,
         )
         self.players[player.name] = player
         if player.pos is None:
@@ -592,6 +640,11 @@ class Environment:
         pass
 
     def init_counters(self):
+        """Initialize the counters in the environment.
+
+        Connect the `ServingWindow`(s) with the `PlateDispenser`.
+        Find and connect the `SinkAddon`s with the `Sink`s
+        """
         plate_dispenser = self.get_counter_of_type(PlateDispenser)
         assert len(plate_dispenser) > 0, "No Plate Return in the environment"
 
@@ -600,8 +653,10 @@ class Environment:
         for counter in self.counters:
             match counter:
                 case ServingWindow():
+                    counter: ServingWindow  # Pycharm type checker does now work for match statements?
                     counter.add_plate_dispenser(plate_dispenser[0])
                 case Sink(pos=pos):
+                    counter: Sink  # Pycharm type checker does now work for match statements?
                     assert len(sink_addons) > 0, "No SinkAddon but normal Sink"
                     closest_addon = self.get_closest(pos, sink_addons)
                     assert 1 - (1 * 0.05) <= np.linalg.norm(
@@ -609,17 +664,23 @@ class Environment:
                     ), f"No SinkAddon connected to Sink at pos {pos}"
                     counter.set_addon(closest_addon)
 
-        pass
-
     @staticmethod
-    def get_closest(pos: npt.NDArray[float], counter: list[Counter]):
-        return min(counter, key=lambda c: np.linalg.norm(c.pos - pos))
+    def get_closest(pos: npt.NDArray[float], counters: list[Counter]):
+        """Find the closest counter for a position
+
+        Args:
+            pos: the position to find the closest one from. Needs to be the same shape as the `Counter.pos` array.
+            counters: target to find the closest one.
+        """
+        return min(counters, key=lambda c: np.linalg.norm(c.pos - pos))
 
     def get_counter_of_type(self, counter_type) -> list[Counter]:
+        """Filter all counters in the environment for a counter type."""
         return list(
             filter(lambda counter: isinstance(counter, counter_type), self.counters)
         )
 
     def reset_env_time(self):
+        """Reset the env time to the initial time, defined by `create_init_env_time`."""
         self.env_time = create_init_env_time()
         log.debug(f"Reset env time to {self.env_time}")
diff --git a/overcooked_simulator/player.py b/overcooked_simulator/player.py
index 63f803c86a1c2575c2cf2a8b8248e8c0a62d116a..6ff77cb692814c8ceebb5dfb0861306f8d9c5984 100644
--- a/overcooked_simulator/player.py
+++ b/overcooked_simulator/player.py
@@ -1,6 +1,17 @@
+"""The player contains the logic which method to call on counters and items for a pick action:
+
+If the player holds nothing, it picks up the content from the counter.
+
+If the item the player holds can be dropped on the counter it will do so.
+
+If the counter is not a sink or plate dispenser, it checks if it can combine the content on the counter with the
+holding object. If so, it picks up the content and combines it on its hands.
+"""
+
+import dataclasses
 import logging
 from collections import deque
-from typing import Optional, Any
+from typing import Optional
 
 import numpy as np
 import numpy.typing as npt
@@ -11,6 +22,18 @@ from overcooked_simulator.game_items import Item, Plate
 log = logging.getLogger(__name__)
 
 
+@dataclasses.dataclass
+class PlayerConfig:
+    """Configure the player attributes in the `environment.yml`."""
+
+    radius: float = 0.4
+    """The size of the player. The size of a counter is 1"""
+    move_dist: float = 0.15
+    """The move distance/speed of the player per action call."""
+    interaction_range: float = 1.6
+    """How far player can interact with counters."""
+
+
 class Player:
     """Class representing a player in the game environment. A player consists of a name, their position and what
     the player is currently holding in the hands.
@@ -21,11 +44,10 @@ class Player:
     def __init__(
         self,
         name: str,
-        player_config: dict[str, Any],
+        player_config: PlayerConfig,
         pos: Optional[npt.NDArray[float]] = None,
     ):
         self.name: str = name
-        self.player_config = player_config
         if pos is not None:
             self.pos: npt.NDArray[float] = np.array(pos, dtype=float)
         else:
@@ -33,10 +55,14 @@ class Player:
 
         self.holding: Optional[Item] = None
 
-        self.radius: float = self.player_config["radius"]
-        self.move_dist: int = self.player_config["move_dist"]
-        self.interaction_range: int = self.player_config["interaction_range"]
+        self.radius: float = player_config.radius
+        """See `PlayerConfig.radius`."""
+        self.move_dist: float = player_config.move_dist
+        """See `PlayerConfig.move_dist`."""
+        self.interaction_range: float = player_config.interaction_range
+        """See `PlayerConfig.interaction_range`."""
         self.facing_direction: npt.NDArray[float] = np.array([0, 1])
+        """Current direction the player looks."""
         self.last_interacted_counter: Optional[
             Counter
         ] = None  # needed to stop progress when moved away
@@ -116,7 +142,8 @@ class Player:
         if isinstance(self.holding, Plate):
             log.debug(self.holding.clean)
 
-    def perform_interact_hold_start(self, counter: Counter):
+    @staticmethod
+    def perform_interact_hold_start(counter: Counter):
         """Starts an interaction with the counter. Should be called for a
         keydown event, for holding down a key on the keyboard.
 
@@ -125,7 +152,8 @@ class Player:
         """
         counter.interact_start()
 
-    def perform_interact_hold_stop(self, counter: Counter):
+    @staticmethod
+    def perform_interact_hold_stop(counter: Counter):
         """Stops an interaction with the counter. Should be called for a
         keyup event, for letting go of a keyboard key.
 
diff --git a/overcooked_simulator/utils.py b/overcooked_simulator/utils.py
index 4e4ab7adac96f14999878ac6acd442f2bc8e03b5..dfb5da0068a533134ad72e85bf14289d295cc585 100644
--- a/overcooked_simulator/utils.py
+++ b/overcooked_simulator/utils.py
@@ -2,6 +2,7 @@ from datetime import datetime
 
 
 def create_init_env_time():
+    """Init time of the environment time, because all environments should have the same internal time."""
     return datetime(
         year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
     )
diff --git a/tests/test_start.py b/tests/test_start.py
index d6010a9e0e373c12673601c8f6a99c55651296d0..afc0dfca16930bc32c5a101dd6f798780b9b7499 100644
--- a/tests/test_start.py
+++ b/tests/test_start.py
@@ -7,7 +7,12 @@ import pytest
 from overcooked_simulator import ROOT_DIR
 from overcooked_simulator.counters import Counter, CuttingBoard
 from overcooked_simulator.game_items import Item
-from overcooked_simulator.overcooked_environment import Action, Environment
+from overcooked_simulator.overcooked_environment import (
+    Action,
+    Environment,
+    ActionType,
+    InterActionData,
+)
 from overcooked_simulator.simulation_runner import Simulator
 from overcooked_simulator.utils import create_init_env_time
 
@@ -89,7 +94,7 @@ def test_movement():
     start_pos = np.array([1, 2])
     sim.register_player(player_name, start_pos)
     move_direction = np.array([1, 0])
-    move_action = Action(player_name, "movement", move_direction)
+    move_action = Action(player_name, ActionType.MOVEMENT, move_direction)
     do_moves_number = 6
     for i in range(do_moves_number):
         sim.enter_action(move_action)
@@ -157,7 +162,7 @@ def test_player_reach():
 
     do_moves_number = 30
     for i in range(do_moves_number):
-        move_action = Action("p1", "movement", np.array([0, -1]))
+        move_action = Action("p1", ActionType.MOVEMENT, np.array([0, -1]))
         sim.enter_action(move_action)
     assert player.can_reach(counter), "Player can reach counter?"
 
@@ -177,9 +182,9 @@ def test_pickup():
     sim.register_player("p1", np.array([2, 3]))
     player = sim.env.players["p1"]
 
-    move_down = Action("p1", "movement", np.array([0, -1]))
-    move_up = Action("p1", "movement", np.array([0, 1]))
-    pick = Action("p1", "pickup", "pickup")
+    move_down = Action("p1", ActionType.MOVEMENT, np.array([0, -1]))
+    move_up = Action("p1", ActionType.MOVEMENT, np.array([0, 1]))
+    pick = Action("p1", ActionType.PICKUP, "pickup")
 
     sim.enter_action(move_down)
     assert player.can_reach(counter), "Player can reach counter?"
@@ -232,13 +237,13 @@ def test_processing():
         player = sim.env.players["p1"]
         player.holding = tomato
 
-        move = Action("p1", "movement", np.array([0, -1]))
-        pick = Action("p1", "pickup", "pickup")
+        move = Action("p1", ActionType.MOVEMENT, np.array([0, -1]))
+        pick = Action("p1", ActionType.PICKUP, "pickup")
 
         sim.enter_action(move)
         sim.enter_action(pick)
 
-        hold_down = Action("p1", "interact", "keydown")
+        hold_down = Action("p1", ActionType.INTERACT, InterActionData.START)
         sim.enter_action(hold_down)
 
         assert tomato.name != "ChoppedTomato", "Tomato is not finished yet."
@@ -247,7 +252,7 @@ def test_processing():
 
         assert tomato.name == "ChoppedTomato", "Tomato should be finished."
 
-        button_up = Action("p1", "interact", "keyup")
+        button_up = Action("p1", ActionType.INTERACT, InterActionData.STOP)
         sim.enter_action(button_up)
     finally:
         sim.stop()