From b5e8fe651d2e4190527c0aa11d1ade774f6a93e0 Mon Sep 17 00:00:00 2001 From: fheinrich <fheinrich@techfak.uni-bielefeld.de> Date: Thu, 7 Dec 2023 10:22:49 +0100 Subject: [PATCH] Added Counter types: ServingWindow, Trash, TomatoDispenser, PlateReturn --- overcooked_simulator/counters.py | 77 ++++++++++++++++++- overcooked_simulator/game_items.py | 6 +- overcooked_simulator/layouts/basic.layout | 8 +- overcooked_simulator/main.py | 13 ++-- .../overcooked_environment.py | 26 ++++++- overcooked_simulator/player.py | 12 ++- overcooked_simulator/pygame_gui/pygame_gui.py | 55 +++++++++++-- 7 files changed, 169 insertions(+), 28 deletions(-) diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index 742b9bb1..aa372ed9 100644 --- a/overcooked_simulator/counters.py +++ b/overcooked_simulator/counters.py @@ -2,7 +2,13 @@ from typing import Optional import numpy as np -from overcooked_simulator.game_items import CuttableItem, HoldableItem +from overcooked_simulator.game_items import ( + CuttableItem, + HoldableItem, + ProgressibleItem, + Plate, + Tomato, +) class Counter: @@ -90,3 +96,72 @@ class CuttingBoard(Counter): def __repr__(self): return f"CuttingBoard({self.occupied_by})" + + +class ServingWindow(Counter): + def drop_off(self, item): + return 5 + + def can_score(self, item): + if isinstance(item, Plate) and isinstance(item.holds, ProgressibleItem): + return item.holds.finished + + def can_drop_off(self, item: HoldableItem): + return self.can_score(item) + + def pick_up(self): + return None + + def __repr__(self): + return "ServingWindow" + + +class PlateReturn(Counter): + def __init__(self, pos): + super().__init__(pos) + self.occupied_by = Plate() + + def pick_up(self): + return Plate() + + def drop_off(self, item): + return 0 + + def can_drop_off(self, item): + return False + + def __repr__(self): + return "PlateReturn" + + +class TomatoDispenser(Counter): + def __init__(self, pos): + super().__init__(pos) + + def pick_up(self): + return Tomato() + + def drop_off(self, item: HoldableItem): + return 0 + + def can_drop_off(self, item: HoldableItem): + return False + + def __repr__(self): + return f"{self.occupied_by}Dispenser" + + +class Trash(Counter): + def pick_up(self): + pass + + def drop_off(self, item: HoldableItem): + if isinstance(item, Plate): + item.holds = None + return -1 + + def can_drop_off(self, item: HoldableItem): + return True + + def __repr__(self): + return "Trash" diff --git a/overcooked_simulator/game_items.py b/overcooked_simulator/game_items.py index a40ad99d..b713fbfd 100644 --- a/overcooked_simulator/game_items.py +++ b/overcooked_simulator/game_items.py @@ -17,10 +17,8 @@ class Plate(HoldableItem): super().__init__() - def can_combine(self, other): - if self.holds is None: - if isinstance(other, HoldableItem): - return True + def can_combine(self, other: HoldableItem): + return self.holds is None def combine(self, other): self.holds = other diff --git a/overcooked_simulator/layouts/basic.layout b/overcooked_simulator/layouts/basic.layout index beb5fc01..d4d883fc 100644 --- a/overcooked_simulator/layouts/basic.layout +++ b/overcooked_simulator/layouts/basic.layout @@ -1,11 +1,11 @@ EEEEEEEEEEE -ECCCCCCCCCE +ECCCCTCCCCE ECEEEEEEECE ECEEEEEEECE +EWEEEEEEEEE ECEEEEEEEEE -ECEEEEEEEEE -ECEEEEEEEEE -ECEEEEEEECE +EPEEEEEEEEE ECEEEEEEECE +ECEEEEEEEXE ECCBBCCCCCE EEEEEEEEEEE diff --git a/overcooked_simulator/main.py b/overcooked_simulator/main.py index 5138cab1..3bdc5528 100644 --- a/overcooked_simulator/main.py +++ b/overcooked_simulator/main.py @@ -4,7 +4,6 @@ from pathlib import Path import numpy as np import pygame -from overcooked_simulator.game_items import Tomato, Plate from overcooked_simulator.player import Player from overcooked_simulator.pygame_gui.pygame_gui import PyGameGUI from overcooked_simulator.simulation_runner import Simulator @@ -14,13 +13,13 @@ def main(): simulator = Simulator(Path("overcooked_simulator/layouts/basic.layout"), 600) player_one_name = "p1" player_two_name = "p2" - simulator.register_player(Player(player_one_name, np.array([100, 200]))) - simulator.register_player(Player(player_two_name, np.array([200, 100]))) + simulator.register_player(Player(player_one_name, np.array([200, 200]))) + simulator.register_player(Player(player_two_name, np.array([100, 200]))) - simulator.env.counters[3].occupied_by = Tomato() - simulator.env.counters[4].occupied_by = Tomato() - simulator.env.counters[6].occupied_by = Plate() - simulator.env.counters[7].occupied_by = Plate() + # simulator.env.counters[3].occupied_by = Tomato() + # simulator.env.counters[4].occupied_by = Tomato() + # simulator.env.counters[6].occupied_by = Plate() + # simulator.env.counters[7].occupied_by = Plate() # TODO maybe read the player names and keyboard keys from config file? keys1 = [ diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index 8aa9f198..2d677389 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -7,7 +7,14 @@ if TYPE_CHECKING: from pathlib import Path import numpy as np from scipy.spatial import distance_matrix -from overcooked_simulator.counters import Counter, CuttingBoard +from overcooked_simulator.counters import ( + Counter, + CuttingBoard, + Trash, + ServingWindow, + TomatoDispenser, + PlateReturn, +) class Action: @@ -62,12 +69,25 @@ class Environment: current_x = self.counter_side_length / 2 for character in line: character = character.capitalize() + pos = np.array([current_x, current_y]) match character: case "C": - counter = Counter(np.array([current_x, current_y])) + counter = Counter(pos) counters.append(counter) case "B": - counter = CuttingBoard(np.array([current_x, current_y])) + counter = CuttingBoard(pos) + counters.append(counter) + case "X": + counter = Trash(pos) + counters.append(counter) + case "W": + counter = ServingWindow(pos) + counters.append(counter) + case "T": + counter = TomatoDispenser(pos) + counters.append(counter) + case "P": + counter = PlateReturn(pos) counters.append(counter) case "E": pass diff --git a/overcooked_simulator/player.py b/overcooked_simulator/player.py index 48dd8c44..971f9024 100644 --- a/overcooked_simulator/player.py +++ b/overcooked_simulator/player.py @@ -2,8 +2,8 @@ from typing import Optional import numpy as np -from overcooked_simulator.counters import Counter -from overcooked_simulator.game_items import HoldableItem +from overcooked_simulator.counters import Counter, Trash +from overcooked_simulator.game_items import HoldableItem, Plate class Player: @@ -72,12 +72,16 @@ class Player: Args: counter: The counter to pick things up from or put things down. """ + if self.holding is None: self.holding = counter.pick_up() elif counter.can_drop_off(self.holding): - counter.drop_off(self.holding) - self.holding = None + if isinstance(counter, Trash) and isinstance(self.holding, Plate): + self.holding.holds = None + else: + counter.drop_off(self.holding) + self.holding = None elif self.holding.can_combine(counter.occupied_by): returned_by_counter = counter.pick_up() diff --git a/overcooked_simulator/pygame_gui/pygame_gui.py b/overcooked_simulator/pygame_gui/pygame_gui.py index 2db2b590..2149535a 100644 --- a/overcooked_simulator/pygame_gui/pygame_gui.py +++ b/overcooked_simulator/pygame_gui/pygame_gui.py @@ -1,7 +1,13 @@ import numpy as np import pygame -from overcooked_simulator.counters import CuttingBoard +from overcooked_simulator.counters import ( + CuttingBoard, + Trash, + TomatoDispenser, + PlateReturn, + ServingWindow, +) from overcooked_simulator.game_items import ProgressibleItem, Plate from overcooked_simulator.game_items import Tomato from overcooked_simulator.overcooked_environment import Action @@ -51,10 +57,10 @@ class PyGameGUI: """Visualisation of the overcooked environmnent and reading keyboard inputs using pygame.""" def __init__( - self, - simulator: Simulator, - player_names: list[str], - player_keys: list[pygame.key], + self, + simulator: Simulator, + player_names: list[str], + player_keys: list[pygame.key], ): self.FPS = 60 self.simulator = simulator @@ -232,6 +238,45 @@ class PyGameGUI: 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): + RETURN = (170, 170, 240) + size = 38 + inner = pygame.Rect( + counter.pos[0] - (size / 2), + counter.pos[1] - (size / 2), + size, + size, + ) + pygame.draw.rect(self.screen, RETURN, 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 counter.occupied_by is not None: self.draw_item(counter.pos, counter.occupied_by) -- GitLab