diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index 79272eb5a6af9185413345b834bb32342fc3fc8e..e2b8cbf902575353cd101bfec90bd3d10ddc42b0 100644 --- a/overcooked_simulator/counters.py +++ b/overcooked_simulator/counters.py @@ -8,7 +8,6 @@ from typing import TYPE_CHECKING, Optional if TYPE_CHECKING: from overcooked_simulator.overcooked_environment import ( GameScore, - SinkManager, ) import numpy as np @@ -20,7 +19,6 @@ from overcooked_simulator.game_items import ( CookingEquipment, Meal, Plate, - ItemInfo, ) @@ -202,15 +200,8 @@ class PlateDispenser(Counter): if self.occupied_by: return self.occupied_by.pop() - # def can_drop_off(self, item: Item) -> bool: - # return False - def can_drop_off(self, item: Item) -> bool: - return ( - not self.occupied_by - or isinstance(item, Plate) - or self.occupied_by[-1].can_combine(item) - ) + return not self.occupied_by or self.occupied_by[-1].can_combine(item) def drop_off(self, item: Item) -> Item | None: """Takes the thing dropped of by the player. @@ -223,8 +214,6 @@ class PlateDispenser(Counter): """ if not self.occupied_by: self.occupied_by.append(item) - elif isinstance(item, Plate): - self.occupied_by.append(item) elif self.occupied_by[-1].can_combine(item): return self.occupied_by[-1].combine(item) return None @@ -316,23 +305,23 @@ class Stove(Counter): class Sink(Counter): - def __init__(self, pos, sink_manager): + def __init__(self, pos, sink_addon=None): super().__init__(pos) self.progressing = False - self.sink_manager: SinkManager = sink_manager - self.occupied_by = None - - # TODO: can put multiple things in here and hold the button to do all. + self.sink_addon: SinkAddon = sink_addon + self.occupied_by = deque() def progress(self): """Called by environment step function for time progression""" if self.progressing: - if isinstance(self.occupied_by, Plate): - self.occupied_by.progress() - if self.occupied_by.finished: - self.progressing = False - self.occupied_by = None - self.sink_manager.update_move_plate() + if self.occupied_by: + self.occupied_by[-1].progress() + if self.occupied_by[-1].finished: + plate = self.occupied_by.pop() + if not self.occupied_by: + self.pause_progress() + plate.finished_call() + self.sink_addon.add_clean_plate(plate) def start_progress(self): """Starts the cutting process.""" @@ -356,26 +345,43 @@ class Sink(Counter): def can_drop_off(self, item: Item) -> bool: return isinstance(item, Plate) and not item.clean + def drop_off(self, item: Item) -> Item | None: + self.occupied_by.appendleft(item) + return None + + def pick_up(self, on_hands: bool = True): + return + + def set_addon(self, sink_addon): + self.sink_addon = sink_addon + class SinkAddon(Counter): - def __init__(self, pos, dispensing: ItemInfo): + def __init__(self, pos, occupied_by=None): super().__init__(pos) - self.dispensing = dispensing - self.number_clean_plates = 0 - self.occupied_by = [ - self.dispensing.create_item() for _ in range(self.number_clean_plates) - ] + self.occupied_by = deque(occupied_by) if occupied_by else deque() def can_drop_off(self, item: Item) -> bool: - return False + return not self.occupied_by or self.occupied_by[-1].can_combine(item) - def add_clean_plate(self): - self.number_clean_plates += 1 - plate = self.dispensing.create_item() - if isinstance(plate, Plate): - plate.finished_call() - self.occupied_by.append(plate) + def drop_off(self, item: Item) -> Item | None: + """Takes the thing dropped of by the player. + + Args: + item: The item to be placed on the counter. + + Returns: TODO Return information, whether the score is affected (Serving Window?) + + """ + if not self.occupied_by: + self.occupied_by.append(item) + elif self.occupied_by[-1].can_combine(item): + return self.occupied_by[-1].combine(item) + return None + + def add_clean_plate(self, plate: Plate): + self.occupied_by.appendleft(plate) def pick_up(self, on_hands: bool = True): - return_this = self.occupied_by.pop() - return return_this + if self.occupied_by: + return self.occupied_by.pop() diff --git a/overcooked_simulator/game_content/environment_config.yaml b/overcooked_simulator/game_content/environment_config.yaml index 39e273e025fc68098c7a3825b04ac84b6fef2000..b1a6890ed31fefcbb1f18a2db0014e489ee62b30 100644 --- a/overcooked_simulator/game_content/environment_config.yaml +++ b/overcooked_simulator/game_content/environment_config.yaml @@ -2,6 +2,6 @@ counter_side_length: 40 world_width: 800 world_height: 600 plates: - clean_plates: 1 - dirty_plates: 0 + clean_plates: 0 + dirty_plates: 10 plate_delay: [ 5, 10 ] \ 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 6c0ad9c2d10fd0bb45f85b65bf757e38a347743a..c79cb07c870e88b012354de3297a914eb6a6f9d0 100644 --- a/overcooked_simulator/game_content/layouts/basic.layout +++ b/overcooked_simulator/game_content/layouts/basic.layout @@ -4,8 +4,8 @@ _#_______#_______ _#_______#_______ _W_______________ _#__A__A_________ -_P_______________ -_#_______#_______ +_B_______________ +_B_______#_______ _#_______X_______ -_##BB##S+#_______ +_#P#S+#S+#_______ _________________ diff --git a/overcooked_simulator/game_items.py b/overcooked_simulator/game_items.py index fb983d7d3dc7f05a1de536a329d323d40c4574dd..c932fed9ef27ae2e0e25cbdee835249b3e2d4554 100644 --- a/overcooked_simulator/game_items.py +++ b/overcooked_simulator/game_items.py @@ -72,7 +72,7 @@ class ItemInfo: def can_start_meal(self, start_item: Item): # TODO check specific order / only specific start items - return any( + return start_item and any( [start_item.name == s for meal in self._start_items for s in meal.needs] ) diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index 5c9e241962fcf4bda3cd7b4b9d6068b0084c8889..593f5defe16479e93a37fbe33f2d478bc6b7e0e8 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -4,7 +4,6 @@ import logging import random from pathlib import Path from threading import Lock -from typing import Optional import numpy as np import numpy.typing as npt @@ -58,18 +57,6 @@ class GameScore: return self.score -class SinkManager: - def __init__(self): - self.sink: Optional[Sink] = None - self.sink_addon: Optional[SinkAddon] = None - - def register_sink_addon(self, sink_addon: SinkAddon): - self.sink_addon = sink_addon - - def update_move_plate(self): - self.sink_addon.add_clean_plate() - - class Environment: """Environment class which handles the game logic for the overcooked-inspired environment. @@ -90,7 +77,6 @@ class Environment: self.item_info = self.load_item_info() self.game_score = GameScore() - self.sink_manager = SinkManager() self.SYMBOL_TO_CHARACTER_MAP = { "#": Counter, # because # looks a bit like a counter @@ -112,7 +98,7 @@ class Environment: self.item_info["Pot"].create_item(), ), # Stove with pot: U because it looks like a pot "S": lambda pos: Sink(pos, self.sink_manager), - "+": lambda pos: SinkAddon(pos, self.item_info["Plate"]), + "+": SinkAddon, } ( @@ -452,17 +438,33 @@ class Environment: plate_dispenser = self.get_counter_of_type(PlateDispenser) assert len(plate_dispenser) > 0, "No Plate Return in the environment" + sink_addons = self.get_counter_of_type(SinkAddon) + for counter in self.counters: match counter: case ServingWindow(): counter.add_plate_dispenser(plate_dispenser[0]) - case Sink(): - ... + case Sink(pos=pos): + assert len(sink_addons) > 0, "No SinkAddon but normal Sink" + closest_addon = self.get_closest(pos, sink_addons) + print( + np.linalg.norm(closest_addon.pos - pos), + self.counter_side_length, + ) + assert self.counter_side_length - ( + self.counter_side_length * 0.05 + ) <= np.linalg.norm( + closest_addon.pos - pos + ), f"No SinkAddon connected to Sink at pos {pos}" + counter.set_addon(closest_addon) case SinkAddon(): ... pass + def get_closest(self, pos: npt.NDArray[float], counter: list[Counter]): + return min(counter, key=lambda c: np.linalg.norm(c.pos - pos)) + def get_counter_of_type(self, counter_type) -> list[Counter]: return list( filter(lambda counter: isinstance(counter, counter_type), self.counters) diff --git a/overcooked_simulator/pygame_gui/visualization.yaml b/overcooked_simulator/pygame_gui/visualization.yaml index 62a327a4da1ff9bc0adf1687f2cbdcb980fd73b3..40aae487457efccaa881ac9a111672eb4fff0a05 100644 --- a/overcooked_simulator/pygame_gui/visualization.yaml +++ b/overcooked_simulator/pygame_gui/visualization.yaml @@ -84,7 +84,7 @@ Sink: width: 0.625 - color: darkslategray1 type: circle - radius: 0.4 + radius: 0.45 SinkAddon: parts: @@ -92,10 +92,21 @@ SinkAddon: type: rect height: 0.875 width: 0.625 - - color: darkslategray1 - type: circle - radius: 0.4 - + - type: rect + color: gray83 + height: 0.8 + width: 0.1 + center_offset: [ -0.4, 0.1 ] + - type: rect + color: gray83 + height: 0.8 + width: 0.1 + center_offset: [ -0.4, -0.1 ] + - type: rect + color: gray83 + height: 0.8 + width: 0.1 + center_offset: [ -0.4, -0.3 ] # Items Tomato: parts: