diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py
index dfe0b24ed1bc4ff842b4932e4d8c790c697ad67e..f3c0f1bc04bee22afaa98860c6efb6fe5ecb6dad 100644
--- a/overcooked_simulator/counters.py
+++ b/overcooked_simulator/counters.py
@@ -131,9 +131,9 @@ class ServingWindow(Counter):
         ):
             if isinstance(item.content, Meal) and item.content.progressed_steps:
                 return item.content.finished
-
-            # TODO: Salad can be always be served. Check, if all needed parts are present.
-            if item.content.name in ["Salad"]:
+            if not item.item_info.steps_needed and len(
+                item.content.item_info.needs
+            ) == len(item.content.parts):
                 return True
         return False
 
diff --git a/overcooked_simulator/game_content/item_info.yaml b/overcooked_simulator/game_content/item_info.yaml
index 4693e59d56ecc6eadc4c8086dcbb3b6f82782f77..cacbf3a82993c8340c19c85943b7f1eb85615be6 100644
--- a/overcooked_simulator/game_content/item_info.yaml
+++ b/overcooked_simulator/game_content/item_info.yaml
@@ -13,12 +13,25 @@ Onion:
   is_cuttable: True
   steps_needed: 700
 
-RawPatty:
+Meat:
+  type: Ingredient
+  is_cuttable: True
+  steps_needed: 500
+
+CookedPatty:
+  type: Meal
+  steps_needed: 500
+  needs: [ ChoppedMeat ]
+  finished_progress_name: CookedPatty
+  equipment: Pan
+
+Bun:
   type: Ingredient
 
 Burger:
   type: Meal
   needs: [ Bun, ChoppedLettuce, ChoppedTomato, CookedPatty ]
+  equipment: Plate
 
 Salad:
   type: Meal
@@ -36,7 +49,7 @@ OnionSoup:
   type: Meal
   finished_progress_name: OnionSoup
   steps_needed: 500
-  needs: [ ChoppedOnion , ChoppedOnion, ChoppedOnion ]
+  needs: [ ChoppedOnion, ChoppedOnion, ChoppedOnion ]
   equipment: Pot
 
 Plate:
@@ -44,3 +57,6 @@ Plate:
 
 Pot:
   type: Equipment
+
+Pan:
+  type: Equipment
\ No newline at end of file
diff --git a/overcooked_simulator/game_content/layouts/basic.layout b/overcooked_simulator/game_content/layouts/basic.layout
index 8d31dac9a5076fa7fccf32ce6f151a87fabd28b1..cccb7a9d9f959f96629055d52210f90cb0cebf63 100644
--- a/overcooked_simulator/game_content/layouts/basic.layout
+++ b/overcooked_simulator/game_content/layouts/basic.layout
@@ -1,11 +1,11 @@
 _________________
-_CCUCTNLCC_______
-_C_______C_______
-_C_______C_______
+_#QU#TNLB#_______
+_#_______M_______
+_#_______#_______
 _W_______________
-_C__A__A_________
+_#__A__A_________
 _P_______________
-_C_______C_______
-_C_______X_______
-_CCBBCCCCC_______
+_#_______#_______
+_#_______X_______
+_##CC#####_______
 _________________
diff --git a/overcooked_simulator/game_items.py b/overcooked_simulator/game_items.py
index 55b6f745620b3a09095d691a5944fd2a5d5ef405..52c79b99e6a59cb5a0756703e28180bc54889145 100644
--- a/overcooked_simulator/game_items.py
+++ b/overcooked_simulator/game_items.py
@@ -20,7 +20,7 @@ class ItemInfo:
     needs: list[ItemInfo] = dataclasses.field(compare=False, default_factory=list)
     equipment: ItemInfo | None = dataclasses.field(compare=False, default=None)
 
-    _start_items: list[ItemInfo] = dataclasses.field(
+    _start_meals: list[ItemInfo] = dataclasses.field(
         compare=False, default_factory=list
     )
 
@@ -32,7 +32,7 @@ class ItemInfo:
             return self.finished_progress_name.replace("*", self.name)
         return self.name
 
-    def create_item(self) -> Item:
+    def create_item(self, parts=None) -> Item:
         match self.type:
             case ItemType.Ingredient:
                 if self.is_cuttable:
@@ -53,22 +53,32 @@ class ItemInfo:
                     steps_needed=self.steps_needed,
                     finished_name=self.get_finished_name(),
                     item_info=self,
+                    parts=parts,
                 )
 
-    def add_start_item_to_equipment(self, start_item: ItemInfo):
-        self._start_items.append(start_item)
+    def add_start_meal_to_equipment(self, start_item: ItemInfo):
+        self._start_meals.append(start_item)
 
-    def can_start_meal(self, start_item: Item):
+    def sort_start_meals(self):
+        self._start_meals.sort(key=lambda item_info: len(item_info.needs))
+
+    def can_start_meal(self, items: list[Item]):
         # TODO check specific order / only specific start items
-        return any(
-            [start_item.name == s for meal in self._start_items for s in meal.needs]
-        )
+        return items and self._return_start_meal(items) is not None
+
+    def start_meal(self, items: list[Item]) -> Item:
+        return self._return_start_meal(items).create_item(parts=items)
 
-    def start_meal(self, start_item: Item) -> Item:
-        for meal in self._start_items:
-            for s in meal.needs:
-                if s == start_item.name:
-                    return meal.create_item()
+    def _return_start_meal(self, items: list[Item]) -> ItemInfo | None:
+        for meal in self._start_meals:
+            satisfied = [False for _ in range(len(items))]
+            for i, p in enumerate(items):
+                for _, n in enumerate(meal.needs):
+                    if not satisfied[i] and p.name == n:
+                        satisfied[i] = True
+                        break
+            if all(satisfied):
+                return meal
 
 
 class Item:
@@ -149,14 +159,23 @@ class CookingEquipment(Item):
         self.content = content
 
     def can_combine(self, other):
+        if other is None:
+            return False
         if self.content is None:
             if isinstance(other, CookingEquipment):
                 return other.can_release_content()
             # TODO check other is start of a meal, create meal
             if isinstance(other, Meal) and self.name == "Plate":
                 return not other.steps_needed or other.finished
-            return self.item_info.can_start_meal(other)
-        return self.content.can_combine(other)
+            return self.item_info.can_start_meal([other])
+        if self.content.can_combine(other):
+            return True
+        if isinstance(other, CookingEquipment) and other.content:
+            other = other.content
+        return self.item_info.can_start_meal(
+            [other]
+            + ([self.content] if self.content.progressed_steps else self.content.parts)
+        )
 
     def combine(self, other):
         if self.content is None:
@@ -167,7 +186,30 @@ class CookingEquipment(Item):
                 self.content = other
                 return
             # find starting meal for other
-            self.content = self.item_info.start_meal(other)
+            self.content = self.item_info.start_meal([other])
+            return
+        if not self.content.can_combine(other):
+            if isinstance(other, CookingEquipment) and other.content:
+                content = other.release()
+                self.content = self.item_info.start_meal(
+                    [content]
+                    + (
+                        [self.content]
+                        if self.content.progressed_steps
+                        else self.content.parts
+                    )
+                )
+                return other
+            else:
+                self.content = self.item_info.start_meal(
+                    [other]
+                    + (
+                        [self.content]
+                        if self.content.progressed_steps
+                        else self.content.parts
+                    )
+                )
+            return
         self.content.combine(other)
 
     def can_progress(self, counter_type="Stove") -> bool:
diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py
index ff5be6b8e66621d2e33f3d9631548b23d7f96b6f..c4242b80389596aa77732ea0e55a5aebd06b5b2e 100644
--- a/overcooked_simulator/overcooked_environment.py
+++ b/overcooked_simulator/overcooked_environment.py
@@ -16,7 +16,7 @@ from overcooked_simulator.counters import (
     ServingWindow,
     Stove,
 )
-from overcooked_simulator.game_items import ItemInfo
+from overcooked_simulator.game_items import ItemInfo, ItemType
 # if TYPE_CHECKING:
 from overcooked_simulator.player import Player
 
@@ -70,8 +70,8 @@ class Environment:
 
         self.game_score = GameScore()
         self.SYMBOL_TO_CHARACTER_MAP = {
-            "C": Counter,
-            "B": CuttingBoard,
+            "#": Counter,
+            "C": CuttingBoard,
             "X": Trash,
             "W": lambda pos: ServingWindow(pos, self.game_score),
             "T": lambda pos: Dispenser(pos, self.item_info["Tomato"]),
@@ -84,6 +84,12 @@ class Environment:
                 pos,
                 self.item_info["Pot"].create_item(),
             ),  # Stove with pot: U because it looks like a pot
+            "Q": lambda pos: Stove(
+                pos,
+                self.item_info["Pan"].create_item(),
+            ),  # Stove with pot: U because it looks like a pot
+            "B": lambda pos: Dispenser(pos, self.item_info["Bun"]),
+            "M": lambda pos: Dispenser(pos, self.item_info["Meat"]),
         }
 
         (
@@ -106,7 +112,11 @@ class Environment:
         for item_name, item_info in item_lookup.items():
             if item_info.equipment:
                 item_info.equipment = item_lookup[item_info.equipment]
-                item_info.equipment.add_start_item_to_equipment(item_info)
+                item_info.equipment.add_start_meal_to_equipment(item_info)
+        for item_name, item_info in item_lookup.items():
+            if item_info.type == ItemType.Equipment:
+                # first select meals with smaller needs / ingredients
+                item_info.sort_start_meals()
         return item_lookup
 
     def parse_layout_file(self, layout_file: Path):
diff --git a/overcooked_simulator/pygame_gui/visualization.yaml b/overcooked_simulator/pygame_gui/visualization.yaml
index df6f702c079771a958a53f8230782ee8dce8fbee..ba2f0deed591d9bcfd6365789c315f32c4db4891 100644
--- a/overcooked_simulator/pygame_gui/visualization.yaml
+++ b/overcooked_simulator/pygame_gui/visualization.yaml
@@ -1,3 +1,5 @@
+# colors: https://www.webucator.com/article/python-color-constants-module/
+
 Kitchen:
   ground_tiles_color: sgigray76
   background_lines: gray79
@@ -58,6 +60,20 @@ OnionDispenser:
       height: 0.8
       width: 0.8
 
+MeatDispenser:
+  parts:
+    - color: indianred1
+      type: rect
+      height: 0.8
+      width: 0.8
+
+BunDispenser:
+  parts:
+    - color: sandybrown
+      type: rect
+      height: 0.8
+      width: 0.8
+
 
 ServingWindow:
   parts:
@@ -92,6 +108,15 @@ Onion:
       radius: 0.25
       color: deeppink4
 
+Bun:
+  parts:
+    - type: circle
+      radius: 0.3
+      color: black
+    - type: circle
+      radius: 0.25
+      color: navajowhite2
+
 Lettuce:
   parts:
     - type: circle
@@ -101,6 +126,16 @@ Lettuce:
       radius: 0.25
       color: emeraldgreen
 
+Meat:
+  parts:
+    - type: circle
+      radius: 0.3
+      color: black
+    - type: circle
+      radius: 0.25
+      color: hotpink
+
+
 ChoppedLettuce:
   parts:
     - type: circle
@@ -157,6 +192,33 @@ ChoppedOnion:
       color: deeppink4
       center_offset: [ 5, 0 ]
 
+ChoppedMeat:
+  parts:
+    - type: circle
+      radius: 0.3
+      color: black
+      center_offset: [ -5, 0 ]
+    - type: circle
+      radius: 0.25
+      color: indianred1
+      center_offset: [ -5, 0 ]
+    - type: circle
+      radius: 0.3
+      color: black
+    - type: circle
+      radius: 0.25
+      color: indianred1
+
+CookedPatty:
+  parts:
+    - type: circle
+      radius: 0.3
+      color: black
+    - type: circle
+      radius: 0.25
+      color: salmon4
+
+
 TomatoSoup:
   parts:
     - type: image
@@ -186,3 +248,17 @@ Pot:
     - type: image
       path: images/pot.png
       size: 0.8
+
+Pan:
+  parts:
+    - type: circle
+      radius: 0.4
+      color: black
+    - type: circle
+      radius: 0.35
+      color: sgigray16
+    - color: orange4
+      type: rect
+      height: 0.5
+      width: 0.1
+      center_offset: [ -0.8, -0.05 ]
\ No newline at end of file