diff --git a/overcooked_simulator/game_content/environment_config.yaml b/overcooked_simulator/game_content/environment_config.yaml
index 00716059a6b64f9aba3a7ebb2fc00b541582d04f..9895330f46f1436dfa1d61e9a2ef632a79f16d06 100644
--- a/overcooked_simulator/game_content/environment_config.yaml
+++ b/overcooked_simulator/game_content/environment_config.yaml
@@ -5,7 +5,7 @@ plates:
   # range of seconds until the dirty plate arrives.
 
 game:
-  time_limit_seconds: 300
+  time_limit_seconds: 100
 
 meals:
   all: true
diff --git a/overcooked_simulator/game_content/study_config.yaml b/overcooked_simulator/game_content/study_config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/overcooked_simulator/gui_2d_vis/controller_tutorial.png b/overcooked_simulator/gui_2d_vis/controller_tutorial.png
new file mode 100644
index 0000000000000000000000000000000000000000..ff48c2ca5ac859a3156bfe5e0befac3ba5e3cd31
Binary files /dev/null and b/overcooked_simulator/gui_2d_vis/controller_tutorial.png differ
diff --git a/overcooked_simulator/gui_2d_vis/drawing.py b/overcooked_simulator/gui_2d_vis/drawing.py
index fce7041227f1d95c9b03fb45e7d1f880cf8d0cd9..f90b6386016cfc2beccc71d7ab0b2d32b3770c75 100644
--- a/overcooked_simulator/gui_2d_vis/drawing.py
+++ b/overcooked_simulator/gui_2d_vis/drawing.py
@@ -133,13 +133,13 @@ class Visualizer:
             grid_size,
         )
 
-        for idx, col in zip(controlled_player_idxs, [colors["blue"], colors["red"]]):
-            pygame.draw.circle(
-                screen,
-                col,
-                np.array(state["players"][idx]["pos"]) * grid_size + (grid_size // 2),
-                (grid_size / 2),
-            )
+        # for idx, col in zip(controlled_player_idxs, [colors["blue"], colors["red"]]):
+        #     pygame.draw.circle(
+        #         screen,
+        #         col,
+        #         np.array(state["players"][idx]["pos"]) * grid_size + (grid_size // 2),
+        #         (grid_size / 2),
+        #     )
 
         self.draw_players(
             screen,
diff --git a/overcooked_simulator/gui_2d_vis/overcooked_gui.py b/overcooked_simulator/gui_2d_vis/overcooked_gui.py
index 3d9562357e6f209e462d7a247111900ff7f10a4d..4b2aa1a2c70c4f6dc884fdd0b1cd1fc083154463 100644
--- a/overcooked_simulator/gui_2d_vis/overcooked_gui.py
+++ b/overcooked_simulator/gui_2d_vis/overcooked_gui.py
@@ -2,7 +2,10 @@ import argparse
 import dataclasses
 import json
 import logging
+import os
 import random
+import signal
+import subprocess
 import sys
 import uuid
 from enum import Enum
@@ -33,12 +36,15 @@ from overcooked_simulator.utils import (
 )
 
 CONNECT_WITH_STUDY_SERVER = False
+USE_AAAMBOS_AGENT = False
 
 
 class MenuStates(Enum):
     Start = "Start"
+    ControllerTutorial = "ControllerTutorial"
+    PreGame = "PreGame"
     Game = "Game"
-    GameTransition = "GameTransition"
+    PostGame = "PostGame"
     End = "End"
 
 
@@ -251,12 +257,6 @@ class PyGameGUI:
         max_height = self.window_height - (2 * self.screen_margin)
 
         self.kitchen_aspect_ratio = self.kitchen_height / self.kitchen_width
-        #
-        # if max_height > max_width:
-        #     self.game_height = max_width * self.kitchen_aspect_ratio
-        # else:
-        #     self.game_width = max_height / self.kitchen_aspect_ratio
-
         if self.kitchen_width > self.kitchen_height:
             self.game_width = max_width
             self.game_height = self.game_width * self.kitchen_aspect_ratio
@@ -283,7 +283,7 @@ class PyGameGUI:
         self.game_width -= residual_x
         self.game_height -= residual_y
 
-    def init_ui_elements(self):
+    def show_start_screen(self):
         self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
         self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json")
 
@@ -324,74 +324,6 @@ class PyGameGUI:
             anchors={"right": "right", "top": "top"},
         )
 
-        reset_button_rect = pygame.Rect((0, 0), (self.screen_margin * 0.75, 50))
-        reset_button_rect.topright = (0, 2 * self.buttons_height)
-        self.reset_button = pygame_gui.elements.UIButton(
-            relative_rect=reset_button_rect,
-            text="RESET",
-            manager=self.manager,
-            object_id="#reset_button",
-            anchors={"right": "right", "top": "top"},
-        )
-
-        self.finished_button = pygame_gui.elements.UIButton(
-            relative_rect=pygame.Rect(
-                (
-                    (self.window_width - self.buttons_width),
-                    (self.window_height - self.buttons_height),
-                ),
-                (self.buttons_width, self.buttons_height),
-            ),
-            text="Finish round",
-            manager=self.manager,
-        )
-
-        self.back_button = pygame_gui.elements.UIButton(
-            relative_rect=pygame.Rect(
-                (
-                    (0),
-                    (self.window_height - self.buttons_height),
-                ),
-                (self.buttons_width, self.buttons_height),
-            ),
-            text="Back to menu",
-            manager=self.manager,
-        )
-
-        self.score_label = pygame_gui.elements.UILabel(
-            text=f"Score: _",
-            relative_rect=pygame.Rect(
-                (0, self.window_height - self.screen_margin),
-                (self.screen_margin * 2, self.screen_margin),
-            ),
-            manager=self.manager,
-            object_id="#score_label",
-        )
-
-        self.timer_label = pygame_gui.elements.UILabel(
-            text="GAMETIME",
-            relative_rect=pygame.Rect(
-                (self.screen_margin, self.window_height - self.screen_margin),
-                (self.game_width, self.screen_margin),
-            ),
-            manager=self.manager,
-            object_id="#timer_label",
-        )
-
-        self.orders_label = pygame_gui.elements.UILabel(
-            text="Orders:",
-            relative_rect=pygame.Rect(0, 0, self.screen_margin, self.screen_margin),
-            manager=self.manager,
-            object_id="#orders_label",
-        )
-
-        self.conclusion_label = pygame_gui.elements.UILabel(
-            text="Your final score was _",
-            relative_rect=pygame.Rect(0, 0, self.window_width, self.window_height),
-            manager=self.manager,
-            object_id="#score_label",
-        )
-
         #######################
 
         player_selection_rect = pygame.Rect(
@@ -429,28 +361,6 @@ class PyGameGUI:
             object_id="#split_players_button",
         )
 
-        next_game_button_rect = pygame.Rect((0, 0), (190, 50))
-        next_game_button_rect.centerx = self.buttons_width // 2 + 100
-        self.next_game_button = pygame_gui.elements.UIButton(
-            relative_rect=next_game_button_rect,
-            manager=self.manager,
-            text="Next game",
-            anchors={"centerx": "centerx", "centery": "centery"},
-            object_id="#split_players_button",
-        )
-
-        retry_button_rect = pygame.Rect((0, 0), (190, 50))
-        retry_button_rect.centerx = self.buttons_width // 2 - 100
-        self.retry_button = pygame_gui.elements.UIButton(
-            relative_rect=retry_button_rect,
-            manager=self.manager,
-            text="Retry last game",
-            anchors={"centerx": "centerx", "centery": "centery"},
-            object_id="#split_players_button",
-        )
-
-        ###################
-
         players_container_rect = pygame.Rect(
             (0, 0),
             (
@@ -547,7 +457,234 @@ class PyGameGUI:
             anchors={"left": "left", "centery": "centery"},
         )
 
-    def draw(self, state):
+        self.update_selection_elements()
+
+    def show_tutorial_screen(self):
+        self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
+        self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json")
+
+        image = pygame.image.load(
+            ROOT_DIR / "gui_2d_vis" / "controller_tutorial.png"
+        ).convert_alpha()
+        image_rect = image.get_rect()
+        image_rect.top = 40
+        self.tutorial_image = pygame_gui.elements.UIImage(
+            image_rect,
+            image,
+            manager=self.manager,
+            anchors={"centerx": "centerx", "top": "top"},
+        )
+        img_height = self.window_height * 0.85
+        img_width = img_height * (image_rect.width / image_rect.height)
+        new_dims = (img_width, img_height)
+        self.tutorial_image.set_dimensions(new_dims)
+
+        button_rect = pygame.Rect((0, 0), (220, 80))
+        button_rect.bottom = -20
+        self.continue_button = pygame_gui.elements.UIButton(
+            relative_rect=button_rect,
+            text="Continue",
+            manager=self.manager,
+            anchors={"centerx": "centerx", "bottom": "bottom"},
+        )
+
+        fullscreen_button_rect = pygame.Rect(
+            (0, 0), (self.buttons_width * 0.7, self.buttons_height)
+        )
+        fullscreen_button_rect.topright = (0, 0)
+        self.fullscreen_button = pygame_gui.elements.UIButton(
+            relative_rect=fullscreen_button_rect,
+            text="Fullscreen",
+            manager=self.manager,
+            object_id="#fullscreen_button",
+            anchors={"right": "right", "top": "top"},
+        )
+
+    def show_pre_game_screen(self):
+        self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
+        self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json")
+
+        image = pygame.image.load(
+            ROOT_DIR / "gui_2d_vis" / "recipe_mock.png"
+        ).convert_alpha()
+        image_rect = image.get_rect()
+        image_rect.top = 50
+        self.tutorial_image = pygame_gui.elements.UIImage(
+            image_rect,
+            image,
+            manager=self.manager,
+            anchors={"centerx": "centerx", "top": "top"},
+        )
+        img_height = self.window_height * 0.7
+        img_width = img_height * (image_rect.width / image_rect.height)
+        new_dims = (img_width, img_height)
+        self.tutorial_image.set_dimensions(new_dims)
+
+        self.level_name = pygame_gui.elements.UILabel(
+            text=f"Next level: {self.layout_file_paths[self.current_layout_idx].stem}",
+            relative_rect=pygame.Rect(
+                (0, 0),
+                (self.window_width * 0.7, self.window_height * 0.2),
+            ),
+            manager=self.manager,
+            object_id="#score_label",
+            anchors={"centerx": "centerx", "top": "top"},
+        )
+
+        button_rect = pygame.Rect((0, 0), (220, 80))
+        button_rect.bottom = -20
+        self.continue_button = pygame_gui.elements.UIButton(
+            relative_rect=button_rect,
+            text="Continue",
+            manager=self.manager,
+            anchors={"centerx": "centerx", "bottom": "bottom"},
+        )
+
+        fullscreen_button_rect = pygame.Rect(
+            (0, 0), (self.buttons_width * 0.7, self.buttons_height)
+        )
+        fullscreen_button_rect.topright = (0, 0)
+        self.fullscreen_button = pygame_gui.elements.UIButton(
+            relative_rect=fullscreen_button_rect,
+            text="Fullscreen",
+            manager=self.manager,
+            object_id="#fullscreen_button",
+            anchors={"right": "right", "top": "top"},
+        )
+
+    def show_game_screen(self):
+        self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
+        self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json")
+
+        reset_button_rect = pygame.Rect((0, 0), (self.screen_margin * 0.75, 50))
+        reset_button_rect.topright = (0, 2 * self.buttons_height)
+        self.reset_button = pygame_gui.elements.UIButton(
+            relative_rect=reset_button_rect,
+            text="RESET",
+            manager=self.manager,
+            object_id="#reset_button",
+            anchors={"right": "right", "top": "top"},
+        )
+
+        self.finished_button = pygame_gui.elements.UIButton(
+            relative_rect=pygame.Rect(
+                (
+                    (self.window_width - self.buttons_width),
+                    (self.window_height - self.buttons_height),
+                ),
+                (self.buttons_width, self.buttons_height),
+            ),
+            text="Finish round",
+            manager=self.manager,
+        )
+
+        self.orders_label = pygame_gui.elements.UILabel(
+            text="Orders:",
+            relative_rect=pygame.Rect(0, 0, self.screen_margin, self.screen_margin),
+            manager=self.manager,
+            object_id="#orders_label",
+        )
+
+        self.score_label = pygame_gui.elements.UILabel(
+            text=f"Score: _",
+            relative_rect=pygame.Rect(
+                (0, self.window_height - self.screen_margin),
+                (self.screen_margin * 2, self.screen_margin),
+            ),
+            manager=self.manager,
+            object_id="#score_label",
+        )
+
+        self.timer_label = pygame_gui.elements.UILabel(
+            text="GAMETIME",
+            relative_rect=pygame.Rect(
+                (self.screen_margin, self.window_height - self.screen_margin),
+                (self.game_width, self.screen_margin),
+            ),
+            manager=self.manager,
+            object_id="#timer_label",
+        )
+
+    def show_post_game_screen(self):
+        self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
+        self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json")
+
+        conclusion_rect = pygame.Rect(0, 0, self.window_width, self.window_height * 0.4)
+        conclusion_rect.top = 50
+        self.conclusion_label = pygame_gui.elements.UILabel(
+            text="Your final score was _",
+            relative_rect=conclusion_rect,
+            manager=self.manager,
+            object_id="#score_label",
+            anchors={"centerx": "centerx", "top": "top"},
+        )
+
+        next_game_button_rect = pygame.Rect((0, 0), (190, 50))
+        next_game_button_rect.center = (self.buttons_width // 2 - 200, 200)
+        self.next_game_button = pygame_gui.elements.UIButton(
+            relative_rect=next_game_button_rect,
+            manager=self.manager,
+            text="Next game",
+            anchors={"centerx": "centerx", "centery": "centery"},
+            object_id="#split_players_button",
+        )
+
+        retry_button_rect = pygame.Rect((0, 0), (190, 50))
+        retry_button_rect.center = (self.buttons_width // 2 + 0, 200)
+        self.retry_button = pygame_gui.elements.UIButton(
+            relative_rect=retry_button_rect,
+            manager=self.manager,
+            text="Retry last game",
+            anchors={"center": "center"},
+            object_id="#split_players_button",
+        )
+
+        finish_study_rect = pygame.Rect((0, 0), (190, 50))
+        finish_study_rect.center = (self.buttons_width // 2 + 200, 200)
+        self.finish_study_button = pygame_gui.elements.UIButton(
+            relative_rect=finish_study_rect,
+            manager=self.manager,
+            text="Finish study",
+            anchors={"center": "center"},
+            object_id="#split_players_button",
+        )
+
+    def show_end_screen(self):
+        self.manager = pygame_gui.UIManager((self.window_width, self.window_height))
+        self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json")
+
+        quit_rect = pygame.Rect(
+            (
+                0,
+                0,
+            ),
+            (self.buttons_width, self.buttons_height),
+        )
+        quit_rect.topright = (0, 0)
+        self.quit_button = pygame_gui.elements.UIButton(
+            relative_rect=quit_rect,
+            text="Quit Game",
+            manager=self.manager,
+            object_id="#quit_button",
+            anchors={"right": "right", "top": "top"},
+        )
+
+    def update_screen(self):
+        match self.menu_state:
+            case MenuStates.Start:
+                self.show_start_screen()
+            case MenuStates.ControllerTutorial:
+                self.show_tutorial_screen()
+            case MenuStates.PreGame:
+                self.show_pre_game_screen()
+            case MenuStates.Game:
+                self.show_game_screen()
+            case MenuStates.PostGame:
+                self.show_post_game_screen()
+            case MenuStates.End:
+                self.show_end_screen()
+
+    def draw_game(self, state):
         """Main visualization function.
 
         Args:            state: The game state returned by the environment."""
@@ -558,9 +695,6 @@ class PyGameGUI:
             [k.current_player for k in self.key_sets],
         )
 
-        # self.manager.draw_ui(self.main_window)
-        self.update_remaining_time(state["remaining_time"])
-
         self.vis.draw_orders(
             screen=self.main_window,
             state=state,
@@ -586,6 +720,7 @@ class PyGameGUI:
         )
 
         self.update_score_label(state)
+        self.update_remaining_time(state["remaining_time"])
 
         if state["info_msg"]:
             for idx, msg in enumerate(reversed(state["info_msg"])):
@@ -635,71 +770,6 @@ class PyGameGUI:
         self.game_width = 0
         self.game_height = 0
         self.set_window_size()
-        self.init_ui_elements()
-
-    def manage_button_visibility(self):
-        match self.menu_state:
-            case MenuStates.Start:
-                self.back_button.hide()
-                self.quit_button.show()
-                self.start_button.show()
-                self.reset_button.hide()
-                self.score_label.hide()
-                self.finished_button.hide()
-                self.timer_label.hide()
-                self.orders_label.hide()
-                self.conclusion_label.hide()
-
-                self.player_selection_container.show()
-
-                self.next_game_button.hide()
-                self.retry_button.hide()
-
-            case MenuStates.Game:
-                self.start_button.hide()
-                self.back_button.hide()
-                self.score_label.show()
-                self.reset_button.show()
-                self.score_label.show()
-                self.finished_button.show()
-                self.timer_label.show()
-                self.orders_label.show()
-                self.conclusion_label.hide()
-
-                self.player_selection_container.hide()
-
-                self.next_game_button.hide()
-                self.retry_button.hide()
-
-            case MenuStates.GameTransition:
-                self.start_button.hide()
-                self.back_button.hide()
-                self.score_label.hide()
-                self.reset_button.hide()
-                self.finished_button.hide()
-                self.timer_label.hide()
-                self.orders_label.hide()
-                self.conclusion_label.hide()
-
-                self.player_selection_container.hide()
-
-                self.next_game_button.show()
-                self.retry_button.show()
-
-            case MenuStates.End:
-                self.start_button.hide()
-                self.back_button.show()
-                self.score_label.hide()
-                self.reset_button.hide()
-                self.finished_button.hide()
-                self.timer_label.hide()
-                self.orders_label.hide()
-                self.conclusion_label.show()
-
-                self.player_selection_container.hide()
-
-                self.next_game_button.hide()
-                self.retry_button.hide()
 
     def update_score_label(self, state):
         score = state["score"]
@@ -776,40 +846,51 @@ class PyGameGUI:
                 print(
                     f'--general_plus="agent_websocket:{self.websocket_url + player_info["client_id"]};player_hash:{player_hash};agent_id:{player_id}"'
                 )
-                # sub = Popen(
-                #     " ".join(
-                #         [
-                #             "exec",
-                #             "aaambos",
-                #             "run",
-                #             "--arch_config",
-                #             str(
-                #                 ROOT_DIR / "game_content" / "agents" / "arch_config.yml"
-                #             ),
-                #             "--run_config",
-                #             str(
-                #                 ROOT_DIR / "game_content" / "agents" / "run_config.yml"
-                #             ),
-                #             f'--general_plus="agent_websocket:{self.websocket_url + player_info["client_id"]};player_hash:{player_hash};agent_id:{player_id}"',
-                #             f"--instance={player_hash}",
-                #         ]
-                #     ),
-                #     shell=True,
-                # )
-                sub = Popen(
-                    " ".join(
-                        [
-                            "python",
-                            str(
-                                ROOT_DIR / "game_content" / "agents" / "random_agent.py"
-                            ),
-                            f'--uri {self.websocket_url + player_info["client_id"]}',
-                            f"--player_hash {player_hash}",
-                            f"--player_id {player_id}",
-                        ]
-                    ),
-                    shell=True,
-                )
+                if USE_AAAMBOS_AGENT:
+                    sub = Popen(
+                        " ".join(
+                            [
+                                "exec",
+                                "aaambos",
+                                "run",
+                                "--arch_config",
+                                str(
+                                    ROOT_DIR
+                                    / "game_content"
+                                    / "agents"
+                                    / "arch_config.yml"
+                                ),
+                                "--run_config",
+                                str(
+                                    ROOT_DIR
+                                    / "game_content"
+                                    / "agents"
+                                    / "run_config.yml"
+                                ),
+                                f'--general_plus="agent_websocket:{self.websocket_url + player_info["client_id"]};player_hash:{player_hash};agent_id:{player_id}"',
+                                f"--instance={player_hash}",
+                            ]
+                        ),
+                        shell=True,
+                    )
+                else:
+                    sub = Popen(
+                        " ".join(
+                            [
+                                "python",
+                                str(
+                                    ROOT_DIR
+                                    / "game_content"
+                                    / "agents"
+                                    / "random_agent.py"
+                                ),
+                                f'--uri {self.websocket_url + player_info["client_id"]}',
+                                f"--player_hash {player_hash}",
+                                f"--player_id {player_id}",
+                            ]
+                        ),
+                        shell=True,
+                    )
                 self.sub_processes.append(sub)
 
             if p + 1 == self.number_humans_to_be_added:
@@ -842,7 +923,7 @@ class PyGameGUI:
         self.kitchen_height = state["kitchen"]["height"]
 
     def start_button_press(self):
-        self.menu_state = MenuStates.Game
+        self.show_start_screen()
 
         self.number_players = (
             self.number_humans_to_be_added + self.number_bots_to_be_added
@@ -862,7 +943,6 @@ class PyGameGUI:
 
         self.set_game_size()
         self.set_window_size()
-        self.init_ui_elements()
         log.debug("Pressed start button")
 
     def back_button_press(self):
@@ -903,10 +983,15 @@ class PyGameGUI:
                     "reason": "finish button pressed",
                 },
             )
-        self.menu_state = MenuStates.GameTransition
+        self.menu_state = MenuStates.PostGame
         self.reset_window_size()
         log.debug("Pressed finished button")
 
+    def fullscreen_button_press(self):
+        self.fullscreen = not self.fullscreen
+        self.set_window_size()
+        self.set_game_size()
+
     def reset_gui_values(self):
         self.currently_controlled_player_idx = 0
         self.number_humans_to_be_added = 1
@@ -983,12 +1068,15 @@ class PyGameGUI:
     def disconnect_websockets(self):
         for sub in self.sub_processes:
             try:
-                sub.kill()
-                # pgrp = os.getpgid(sub.pid)
-                # os.killpg(pgrp, signal.SIGINT)
-                # subprocess.run(
-                #     "kill $(ps aux | grep 'aaambos' | awk '{print $2}')", shell=True
-                # )
+                if USE_AAAMBOS_AGENT:
+                    pgrp = os.getpgid(sub.pid)
+                    os.killpg(pgrp, signal.SIGINT)
+                    subprocess.run(
+                        "kill $(ps aux | grep 'aaambos' | awk '{print $2}')", shell=True
+                    )
+                else:
+                    sub.kill()
+
             except ProcessLookupError:
                 pass
 
@@ -1008,10 +1096,7 @@ class PyGameGUI:
 
         self.reset_window_size()
 
-        self.init_ui_elements()
-        self.manage_button_visibility()
-
-        self.update_selection_elements()
+        self.show_start_screen()
 
         # Game loop
         self.running = True
@@ -1019,101 +1104,121 @@ class PyGameGUI:
             try:
                 self.time_delta = clock.tick(self.FPS) / 1000
 
-                # print(clock.get_time())
                 for event in pygame.event.get():
                     if event.type == pygame.QUIT:
                         self.running = False
 
-                    elif event.type == pygame.VIDEORESIZE:
-                        # scrsize = event.size
-                        self.window_width_windowed = event.w
-                        self.window_height_windowed = event.h
-                        self.set_game_size()
-                        self.set_window_size()
-                        self.init_ui_elements()
-                        self.manage_button_visibility()
-
                     if event.type == pygame_gui.UI_BUTTON_PRESSED:
-                        match event.ui_element:
-                            case self.start_button:
-                                if not (
-                                    self.number_humans_to_be_added
-                                    + self.number_bots_to_be_added
-                                ):
-                                    continue
-                                self.start_button_press()
-
-                            case self.back_button:
-                                self.back_button_press()
-                                self.disconnect_websockets()
-
-                            case self.finished_button:
-                                self.finished_button_press()
-                                self.disconnect_websockets()
-
-                            case self.quit_button:
-                                self.quit_button_press()
-                                self.disconnect_websockets()
-
-                            case self.reset_button:
-                                self.reset_button_press()
-                                self.disconnect_websockets()
-                                self.start_button_press()
-
-                            case self.add_human_player_button:
-                                self.number_humans_to_be_added += 1
-                            case self.remove_human_button:
-                                self.number_humans_to_be_added = max(
-                                    0, self.number_humans_to_be_added - 1
-                                )
-                            case self.add_bot_button:
-                                self.number_bots_to_be_added += 1
-                            case self.remove_bot_button:
-                                self.number_bots_to_be_added = max(
-                                    0, self.number_bots_to_be_added - 1
-                                )
-                            case self.multiple_keysets_button:
-                                self.multiple_keysets = not self.multiple_keysets
-                                self.split_players = False
-                            case self.split_players_button:
-                                self.split_players = not self.split_players
-                                if self.split_players:
-                                    self.player_minimum = 2
-                                else:
-                                    self.player_minimum = 1
-
-                            case self.retry_button:
-                                self.start_button_press()
-
-                            case self.next_game_button:
-                                self.current_layout_idx += 1
-                                if self.current_layout_idx == len(
-                                    self.layout_file_paths
-                                ):
-                                    self.current_layout_idx = 0
-                                    self.start_button_press()
-                                else:
-                                    log.debug(
-                                        f"LEVEL: {self.layout_file_paths[self.current_layout_idx]}"
-                                    )
-                                    self.start_button_press()
-
-                            case self.fullscreen_button:
-                                self.fullscreen = not self.fullscreen
-                                if self.fullscreen:
-                                    self.window_width = self.window_width_fullscreen
-                                    self.window_height = self.window_height_fullscreen
-                                else:
-                                    self.window_width = self.window_width_windowed
-                                    self.window_height = self.window_height_windowed
-                                self.set_game_size()
-                                self.set_window_size()
-                                self.init_ui_elements()
-
+                        match self.menu_state:
+                            ############################################
+                            case MenuStates.Start:
+                                match event.ui_element:
+                                    case self.start_button:
+                                        if not (
+                                            self.number_humans_to_be_added
+                                            + self.number_bots_to_be_added
+                                        ):
+                                            continue
+                                        self.menu_state = MenuStates.ControllerTutorial
+
+                                    case self.quit_button:
+                                        self.quit_button_press()
+                                        self.disconnect_websockets()
+
+                                    case self.add_human_player_button:
+                                        self.number_humans_to_be_added += 1
+                                    case self.remove_human_button:
+                                        self.number_humans_to_be_added = max(
+                                            0, self.number_humans_to_be_added - 1
+                                        )
+                                    case self.add_bot_button:
+                                        self.number_bots_to_be_added += 1
+                                    case self.remove_bot_button:
+                                        self.number_bots_to_be_added = max(
+                                            0, self.number_bots_to_be_added - 1
+                                        )
+                                    case self.multiple_keysets_button:
+                                        self.multiple_keysets = (
+                                            not self.multiple_keysets
+                                        )
+                                        self.split_players = False
+                                    case self.split_players_button:
+                                        self.split_players = not self.split_players
+                                        if self.split_players:
+                                            self.player_minimum = 2
+                                        else:
+                                            self.player_minimum = 1
+
+                                    case self.fullscreen_button:
+                                        self.fullscreen_button_press()
+
+                            ############################################
+
+                            case MenuStates.ControllerTutorial:
+                                match event.ui_element:
+                                    case self.continue_button:
+                                        self.menu_state = MenuStates.PreGame
+                                    case self.fullscreen_button:
+                                        self.fullscreen_button_press()
+
+                            ############################################
+
+                            case MenuStates.PreGame:
+                                match event.ui_element:
+                                    case self.continue_button:
+                                        self.menu_state = MenuStates.Game
+                                        self.start_button_press()
+                                    case self.fullscreen_button:
+                                        self.fullscreen_button_press()
+
+                            ############################################
+
+                            case MenuStates.Game:
+                                match event.ui_element:
+                                    case self.finished_button:
+                                        self.menu_state = MenuStates.PostGame
+                                        self.disconnect_websockets()
+                                        self.finished_button_press()
+                                    case self.reset_button:
+                                        self.reset_button_press()
+                                        self.disconnect_websockets()
+                                        self.start_button_press()
+
+                            ############################################
+
+                            case MenuStates.PostGame:
+                                match event.ui_element:
+                                    case self.retry_button:
+                                        self.start_button_press()
+                                        self.menu_state = MenuStates.PreGame
+
+                                    case self.next_game_button:
+                                        self.current_layout_idx += 1
+                                        if self.current_layout_idx == len(
+                                            self.layout_file_paths
+                                        ):
+                                            self.current_layout_idx = 0
+                                        else:
+                                            log.debug(
+                                                f"LEVEL: {self.layout_file_paths[self.current_layout_idx]}"
+                                            )
+                                        self.start_button_press()
+                                        self.menu_state = MenuStates.PreGame
+
+                                    case self.finish_study_button:
+                                        self.menu_state = MenuStates.End
+
+                            ############################################
+
+                            case MenuStates.End:
+                                match event.ui_element:
+                                    case self.quit_button:
+                                        self.quit_button_press()
+                                        self.disconnect_websockets()
+
+                        self.update_screen()
                         self.update_selection_elements()
 
-                        self.manage_button_visibility()
-
                     if (
                         event.type in [pygame.KEYDOWN, pygame.KEYUP]
                         and self.menu_state == MenuStates.Game
@@ -1141,9 +1246,8 @@ class PyGameGUI:
                         if state["ended"]:
                             self.finished_button_press()
                             self.disconnect_websockets()
-                            self.manage_button_visibility()
                         else:
-                            self.draw(state)
+                            self.draw_game(state)
 
                             game_screen_rect = self.game_screen.get_rect()
 
diff --git a/overcooked_simulator/gui_2d_vis/recipe_mock.png b/overcooked_simulator/gui_2d_vis/recipe_mock.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ac719852dfd2470712a56ee249f86baa7a891d6
Binary files /dev/null and b/overcooked_simulator/gui_2d_vis/recipe_mock.png differ
diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py
index d157ce604b478f28afe1c827f4a7e71b30aa3a49..15bf39c86263f76e795990919533e9f08c047995 100644
--- a/overcooked_simulator/overcooked_environment.py
+++ b/overcooked_simulator/overcooked_environment.py
@@ -431,6 +431,8 @@ class Environment:
 
         grid = []
 
+        max_width = 0
+
         lines = list(filter(lambda l: l != "", lines))
         for line in lines:
             line = line.replace(" ", "")
@@ -438,6 +440,7 @@ class Environment:
                 break
             current_x: float = starting_at
             grid_line = []
+
             for character in line:
                 # character = character.capitalize()
                 pos = np.array([current_x, current_y])
@@ -460,10 +463,19 @@ class Environment:
 
                 current_x += 1
 
+            if len(line) >= max_width:
+                max_width = len(line)
+
             grid.append(grid_line)
             current_y += 1
 
-        self.kitchen_width: float = len(lines[0]) + starting_at
+        for line in grid:
+            print(line)
+        grid = [line + ([0] * (max_width - len(line))) for line in grid]
+        for line in grid:
+            print(line)
+
+        self.kitchen_width: float = max_width + starting_at
         self.kitchen_height = current_y
 
         self.determine_counter_orientations(