-
Fabian Heinrich authoredFabian Heinrich authored
overcooked_environment.py 5.44 KiB
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from overcooked_simulator.player import Player
from pathlib import Path
import numpy as np
class Counter:
"""Simple class for a counter at a specified position (center of counter). Can hold things on top.
"""
def __init__(self, pos: np.array):
self.pos = pos
self.occupied_by = None
def __repr__(self):
return f"Counter(pos:{str(self.pos)},holds:{self.occupied_by})"
class Action:
"""Action class, specifies player, action type and action itself.
"""
def __init__(self, player, act_type, action):
self.player = player
self.act_type = act_type
assert self.act_type in ["movement", "pickup", "interact"], "Unknown action type"
self.action = action
class Environment:
"""Environment class which handles the game logic for the overcooked-inspired environment.
Handles player movement, collision-detection, counters, cooking processes, recipes, incoming orders, time.
"""
def __init__(self):
self.players = {}
self.counter_side_length = 40
self.layout_path = Path("overcooked_simulator/layouts/basic.layout")
self.counters = self.create_counters(self.layout_path)
self.score = 0
def create_counters(self, layout_file: Path):
"""Creates layout of kitchen counters in the environment based on layout file.
Counters are arranged in a fixed size grid starting at [0,0]. The center of the first counter is at
[counter_size/2, counter_size/2], counters are directly next to each other (of no empty space is specified
in layout).
Args:
layout_file: Path to the layout file.
"""
current_y = self.counter_side_length / 2
counters = []
with open(layout_file, "r") as layout_file:
lines = layout_file.readlines()
for line in lines:
line = line.replace("\n", "").replace(" ", "") # remove newline char
current_x = self.counter_side_length / 2
for character in line:
character = character.capitalize()
if character == "C":
counter = Counter(np.array([current_x, current_y]))
counters.append(counter)
current_x += self.counter_side_length
elif character == "E":
pass
current_y += self.counter_side_length
return counters
def perform_action(self, action: Action):
"""Performs an action of a player in the environment. Maps different types of action inputs to the
correct execution of the players.
Possible action types are movement, pickup and interact actions.
Args:
action: The action to be performed
"""
assert action.player in self.players.keys(), "Unknown player."
player = self.players[action.player]
if action.act_type == "movement":
self.perform_movement(player, action.action)
elif action.act_type == "pickup":
self.perform_pickup(player)
elif action.act_type == "interact":
self.perform_interact(player)
def get_closest_counter(self, player: Player):
"""Determines the closest counter in the environment of a player.
Args:
player: The player for which to find the closest counter
Returns: The closest counter for the given player.
"""
pass
def perform_pickup(self, player: Player):
"""Performs the game action corresponding to picking up an item
Args:
player: The player which performs the pickup action.
Returns: TODO?
"""
pass
def perform_interact(self, player: Player):
"""Performs the game action corresponding to interacting with a counter or other object.
Args:
player: The player which performs the interaction.
Returns: TODO?
"""
pass
def perform_movement(self, player: Player, action):
"""Moves a player in the direction specified in the action.action. If the player collides with a
counter or other player through this movement, then they are not moved.
Args:
player: The player to move.
action: The Action which now contains a unit-2d-vector of the movement direction
"""
pass
def detect_collision(self, player: Player):
"""Detect collisions between the player and other players or counters.
Args:
player: The player for which to check collisions.
Returns: True if the player is intersecting with any object in the environment.
"""
pass
def step(self):
"""Performs a step of the environment. Affects time based events such as cooking or cutting things, orders
and timelimits.
"""
pass
def get_state(self):
"""Get the current state of the game environment. The state here is accessible by the current python objects.
Returns: Dict of lists of the current relevant game objects.
"""
return {"players": self.players,
"counters": self.counters,
"score": self.score}
def get_state_json(self):
"""Get the current state of the game environment as a json-like nested dictionary.
Returns: Json-like string of the current game state.
"""
pass