diff --git a/overcooked_simulator/game_items.py b/overcooked_simulator/game_items.py
index 1d5098de7b8923d316851859430221a53554abea..a58221de7d5d027bc1598c7487c20c455dbce491 100644
--- a/overcooked_simulator/game_items.py
+++ b/overcooked_simulator/game_items.py
@@ -62,7 +62,7 @@ class ProgressibleItem:
         self.steps_needed = steps_needed
         self.finished = finished
         self.finished_name = (
-            f"Cutted{self.name}" if finished_name is None else finished_name
+            f"Chopped{self.name}" if finished_name is None else finished_name
         )
 
     def progress(self):
@@ -177,6 +177,9 @@ class Meal(Item):
 
 
 class Soup(ProgressibleItem, Meal):
+    def __init__(self):
+        super().__init__(finished_name="CookedSoup")
+
     def can_progress(self) -> bool:
         return len(self.parts) == 3
 
diff --git a/overcooked_simulator/pygame_gui/pygame_gui.py b/overcooked_simulator/pygame_gui/pygame_gui.py
index 7488799fc767716bb4f6e4ec994545bbee71e9de..0393c8c3e23cac3d5645ddb32b9bceaca2408071 100644
--- a/overcooked_simulator/pygame_gui/pygame_gui.py
+++ b/overcooked_simulator/pygame_gui/pygame_gui.py
@@ -3,44 +3,28 @@ from pathlib import Path
 
 import numpy as np
 import pygame
+import yaml
 
 from overcooked_simulator import ROOT_DIR
-from overcooked_simulator.counters import (
-    CuttingBoard,
-    Trash,
-    TomatoDispenser,
-    PlateReturn,
-    ServingWindow,
-    Stove,
-)
 from overcooked_simulator.game_items import (
     ProgressibleItem,
     Plate,
     Item,
-    Pot,
-    Soup,
+    CookingEquipment,
+    Meal,
 )
-from overcooked_simulator.game_items import Tomato
 from overcooked_simulator.overcooked_environment import Action
 from overcooked_simulator.simulation_runner import Simulator
 
-WHITE = (255, 255, 255)
-GREY = (190, 190, 190)
-BLACK = (0, 0, 0)
 COUNTER_COLOR = (240, 240, 240)
-LIGHTGREY = (220, 220, 220)
 GREEN = (0, 255, 0)
 RED = (255, 0, 0)
 BLUE = (0, 0, 255)
-YELLOW = (255, 255, 0)
-BACKGROUND_COLOR = GREY
+WHITE = (255, 255, 255)
+BACKGROUND_COLOR = (190, 190, 190)
 BACKGROUND_LINES_COLOR = (200, 200, 200)
-KNIFE_COLOR = (120, 120, 120)
-PLATE_RETURN_COLOR = (170, 170, 240)
-BOARD_COLOR = (239, 193, 151)
-POT_COLOR = (130, 130, 130)
 
-USE_COOK_SPRITE = True
+PLAYER_DEBUG_VIZ = True
 
 
 class PlayerKeySet:
@@ -98,6 +82,9 @@ class PyGameGUI:
             for player_name, keys in zip(self.player_names, self.player_keys)
         ]
 
+        with open(ROOT_DIR / "pygame_gui/visualization.yaml", "r") as file:
+            self.visualization_config = yaml.safe_load(file)
+
         self.images_path = Path(ROOT_DIR, "pygame_gui", "images")
 
     def send_action(self, action: Action):
@@ -163,28 +150,18 @@ class PyGameGUI:
             state: The game state returned by the environment.
         """
         for player in state["players"].values():
-            if USE_COOK_SPRITE:
-                image = pygame.image.load(
-                    self.images_path / "pixel_cook.png"
-                ).convert_alpha()
-
-                rel_x, rel_y = player.facing_direction
-                angle = -np.rad2deg(math.atan2(rel_y, rel_x)) + 90
-
-                image = pygame.transform.scale(image, (40, 40))
-                image = pygame.transform.rotate(image, angle)
-                rect = image.get_rect()
-                rect.center = player.pos
-                self.screen.blit(image, rect)
-            else:
+            if PLAYER_DEBUG_VIZ:
                 pos = player.pos
                 size = player.radius
                 color1 = RED if player.name == "p1" else GREEN
                 color2 = WHITE
 
-                rect = pygame.Rect(pos[0] - (size / 2), pos[1] - (size / 2), size, size)
                 pygame.draw.circle(self.screen, color2, pos, size)
-                pygame.draw.rect(self.screen, color1, rect)
+                pygame.draw.circle(self.screen, BLUE, pos, size, width=1)
+                pygame.draw.circle(
+                    self.screen, BLUE, pos, player.interaction_range, width=1
+                )
+                pygame.draw.circle(self.screen, color1, pos, size // 2)
 
                 pos = player.pos
                 facing = player.facing_direction
@@ -194,67 +171,90 @@ class PyGameGUI:
                     (
                         (pos[0] + (facing[1] * 5), pos[1] - (facing[0] * 5)),
                         (pos[0] - (facing[1] * 5), pos[1] + (facing[0] * 5)),
-                        player.pos + (facing * 20),
+                        player.pos + (facing * 25),
                     ),
                 )
+            else:
+                img_path = self.visualization_config["Cook"]["parts"][0]["path"]
+                image = pygame.image.load(
+                    ROOT_DIR / Path("pygame_gui") / img_path
+                ).convert_alpha()
+                rel_x, rel_y = player.facing_direction
+                angle = -np.rad2deg(math.atan2(rel_y, rel_x)) + 90
+
+                size = self.visualization_config["Cook"]["parts"][0]["size"]
+                image = pygame.transform.scale(image, (size, size))
+                image = pygame.transform.rotate(image, angle)
+                rect = image.get_rect()
+                rect.center = player.pos
+                self.screen.blit(image, rect)
 
             if player.holding is not None:
                 holding_item_pos = player.pos + (20 * player.facing_direction)
                 self.draw_item(holding_item_pos, player.holding)
 
     def draw_item(self, pos, item: Item):
-        """Visualisation of an item at the specified position. On a counter or in the hands of the player."""
-        if isinstance(item, Tomato):
-            if item.finished:
-                image = pygame.image.load(
-                    self.images_path / "tomato_cut.png"
-                ).convert_alpha()
-            else:
-                image = pygame.image.load(
-                    self.images_path / "tomato.png"
-                ).convert_alpha()
-            rect = image.get_rect()
-            rect.center = pos
-            self.screen.blit(image, rect)
+        """Visualisation of an item at the specified position. On a counter or in the hands of the player.
+        The visual composition of the item is read in from visualization.yaml file, where it is specified as
+        different parts to be drawn.
+
+        Args:
+            item: The item do be drawn in the game.
+        """
+
+        if item.name == "Tomato":
+            print(item)
+
+        if not isinstance(item, Meal):
+            image = pygame.image.load(
+                ROOT_DIR
+                / Path("pygame_gui")
+                / self.visualization_config[item.name]["parts"][0]["path"]
+            ).convert_alpha()
+
+            size = self.visualization_config[item.name]["parts"][0]["size"]
+            image = pygame.transform.scale(image, (size, size))
 
-        if isinstance(item, Plate):
-            image = pygame.image.load(self.images_path / "plate.png").convert_alpha()
             rect = image.get_rect()
             rect.center = pos
             self.screen.blit(image, rect)
 
-            if item.holds is not None:
-                self.draw_item(pos, item.holds)
-
-        if isinstance(item, Pot):
-            pot_size = 15
-            pygame.draw.circle(self.screen, GREY, pos, pot_size)
-            pygame.draw.circle(self.screen, POT_COLOR, pos, pot_size, width=2)
-            if item.content:
-                self.draw_item(pos, item.content)
-        if isinstance(item, Soup):
-            if not item.finished:
-                match len(item.parts):
-                    case 1:
-                        pygame.draw.circle(self.screen, RED, pos, 4)
-                    case 2:
-                        pygame.draw.circle(self.screen, RED, pos, 8)
-                    case 3:
-                        pygame.draw.circle(self.screen, RED, pos, 12)
-            else:
-                """https://www.readersdigest.ca/wp-content/uploads/2020/11/The-Best-Ever-Tomato-Soup_EXPS_THSO18_222724_D03_06_5b-4.jpg"""
-                image = pygame.image.load(
-                    self.images_path / "tomato_soup.png"
-                ).convert_alpha()
-                image = pygame.transform.scale(image, (24, 24))
-                rect = image.get_rect()
-                rect.center = pos
-                self.screen.blit(image, rect)
-
         if isinstance(item, ProgressibleItem) and not item.finished:
             self.draw_progress_bar(pos, item.progressed_steps, item.steps_needed)
 
+        if isinstance(item, Plate) and item.holds:
+            self.draw_item(pos, item.holds)
+
+        if isinstance(item, CookingEquipment) and item.content:
+            self.draw_item(pos, item.content)
+
+        if isinstance(item, Meal) and item.parts:
+            if (
+                isinstance(item, Meal)
+                and isinstance(item, ProgressibleItem)
+                and item.parts
+            ):
+                if not item.finished:
+                    match len(item.parts):
+                        case 1:
+                            pygame.draw.circle(self.screen, RED, pos, 4)
+                        case 2:
+                            pygame.draw.circle(self.screen, RED, pos, 8)
+                        case 3:
+                            pygame.draw.circle(self.screen, RED, pos, 12)
+                else:
+                    image = pygame.image.load(
+                        ROOT_DIR
+                        / Path("pygame_gui")
+                        / self.visualization_config[item.name]["parts"][0]["path"]
+                    ).convert_alpha()
+                    image = pygame.transform.scale(image, (24, 24))
+                    rect = image.get_rect()
+                    rect.center = pos
+                    self.screen.blit(image, rect)
+
     def draw_progress_bar(self, pos, current, needed):
+        """Visualize progress of progressing item as a green bar under the item."""
         if current != 0:
             bar_height = self.counter_size * 0.2
             progress_width = (current / needed) * self.counter_size
@@ -268,6 +268,8 @@ class PyGameGUI:
 
     def draw_counter(self, counter):
         """Visualisation of a counter at its position. If it is occupied by an item, it is also shown.
+        The visual composition of the counter is read in from visualization.yaml file, where it is specified as
+        different parts to be drawn.
 
         Args:
             counter: The counter to visualize.
@@ -281,69 +283,29 @@ class PyGameGUI:
         )
         pygame.draw.rect(self.screen, COUNTER_COLOR, counter_rect_outline)
 
-        if isinstance(counter, CuttingBoard):
-            board_size = 30
-            board_rect = pygame.Rect(
-                counter.pos[0] - (board_size / 2),
-                counter.pos[1] - (board_size / 2),
-                board_size,
-                board_size,
-            )
-            pygame.draw.rect(self.screen, BOARD_COLOR, board_rect)
-
-            knife_rect = pygame.Rect(counter.pos[0] + 6, counter.pos[1] - 8, 5, 20)
-            pygame.draw.rect(self.screen, KNIFE_COLOR, knife_rect)
-
-        if isinstance(counter, PlateReturn):
-            size = 38
-            inner = pygame.Rect(
-                counter.pos[0] - (size / 2),
-                counter.pos[1] - (size / 2),
-                size,
-                size,
-            )
-            pygame.draw.rect(self.screen, PLATE_RETURN_COLOR, inner)
-
-        if isinstance(counter, Trash):
-            pygame.draw.circle(
-                self.screen,
-                (80, 80, 80),
-                counter.pos,
-                self.counter_size * 0.4,
-            )
-            pygame.draw.circle(self.screen, BLACK, counter.pos, self.counter_size * 0.3)
-        if isinstance(counter, TomatoDispenser):
-            board_size = 32
-            board_rect = pygame.Rect(
-                counter.pos[0] - (board_size / 2),
-                counter.pos[1] - (board_size / 2),
-                board_size,
-                board_size,
-            )
-            pygame.draw.rect(self.screen, RED, board_rect)
-            self.draw_item(counter.pos, Tomato())
-
-        if isinstance(counter, ServingWindow):
-            board_size = 33
-            board_rect = pygame.Rect(
-                counter.pos[0] - (board_size / 2),
-                counter.pos[1] - (board_size / 2),
-                board_size,
-                board_size,
-            )
-            pygame.draw.rect(self.screen, YELLOW, board_rect)
-
-        if isinstance(counter, Stove):
-            stove_width = 35
-            stove_height = 25
-            stove_rect = pygame.Rect(
-                counter.pos[0] - (stove_width / 2),
-                counter.pos[1] - (stove_height / 2),
-                stove_width,
-                stove_height,
-            )
-            pygame.draw.rect(self.screen, BLACK, stove_rect)
-            pygame.draw.circle(self.screen, RED, center=counter.pos, radius=10)
+        for part in self.visualization_config[counter.__class__.__name__]["parts"]:
+            if part["type"] == "rect":
+                height = part["height"]
+                width = part["width"]
+                color = part["color"]
+                if "center_offset" in part:
+                    dx, dy = part["center_offset"]
+                    rect = pygame.Rect(counter.pos[0] + dx, counter.pos[1] + dy, 5, 20)
+                    pygame.draw.rect(self.screen, color, rect)
+                else:
+                    rect = pygame.Rect(
+                        counter.pos[0] - (height / 2),
+                        counter.pos[1] - (width / 2),
+                        height,
+                        width,
+                    )
+                pygame.draw.rect(self.screen, color, rect)
+
+            elif part["type"] == "circle":
+                radius = part["radius"]
+                color = part["color"]
+                pygame.draw.circle(self.screen, color, counter.pos, radius)
+
         if counter.occupied_by is not None:
             if isinstance(counter.occupied_by, list):
                 for i, o in enumerate(counter.occupied_by):
diff --git a/overcooked_simulator/pygame_gui/visualization.yaml b/overcooked_simulator/pygame_gui/visualization.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..dc200b30a00b90ee40ee1ed664f24a9448457e06
--- /dev/null
+++ b/overcooked_simulator/pygame_gui/visualization.yaml
@@ -0,0 +1,101 @@
+Counter:
+  parts:
+    - type: "rect"
+      height: 40
+      width: 40
+      color: [ 240, 240, 240 ]
+
+CuttingBoard:
+  parts:
+    - type: "rect"
+      height: 30
+      width: 30
+      color: [ 239, 193, 151 ]
+    - type: "rect"
+      height: 5
+      width: 20
+      center_offset: [ +6, -8 ]
+      color: [ 120, 120, 120 ]
+
+PlateReturn:
+  parts:
+    - type: "rect"
+      height: 38
+      width: 38
+      color: [ 170, 170, 240 ]
+
+Trash:
+  parts:
+    - type: "circle"
+      radius: 16
+      color: [ 0, 0, 0 ]
+    - type: "circle"
+      radius: 15
+      color: [ 80, 80, 80 ]
+
+TomatoDispenser:
+  parts:
+    - color: [ 255, 0, 0 ]
+      type: "rect"
+      height: 32
+      width: 32
+
+ServingWindow:
+  parts:
+    - color: [ 255, 255, 0 ]
+      type: "rect"
+      height: 33
+      width: 33
+
+Stove:
+  parts:
+    - color: [ 0, 0, 0 ]
+      type: "rect"
+      height: 35
+      width: 25
+    - color: [ 255, 0, 0 ]
+      type: "circle"
+      radius: 10
+
+# Items
+Tomato:
+  parts:
+    - type: "image"
+      path: "images/tomato.png"
+      size: 40
+
+ChoppedTomato:
+  parts:
+    - type: "image"
+      path: "images/tomato_cut.png"
+      size: 40
+
+CookedSoup:
+  parts:
+    - type: "image"
+      path: "images/tomato_soup.png"
+      size: 24
+
+Soup:
+  parts:
+    - type: "image"
+      path: "images/tomato_soup.png"
+      size: 24
+
+Cook:
+  parts:
+    - type: "image"
+      path: "images/pixel_cook.png"
+      size: 40
+
+Plate:
+  parts:
+    - type: "image"
+      path: "images/plate.png"
+      size: 40
+
+Pot:
+  parts:
+    - type: "image"
+      path: "images/pot.png"
+      size: 32