Skip to content
Snippets Groups Projects
Commit 83f5aacc authored by Annika Österdiekhoff's avatar Annika Österdiekhoff
Browse files

merge main

parents 380c84cc 41b0065a
No related branches found
No related tags found
1 merge request!45Resolve "Controller Support"
Pipeline #46212 passed
Showing
with 1143 additions and 107 deletions
......@@ -50,7 +50,7 @@ def main(cli_args=None):
print("Received Keyboard interrupt")
finally:
if game_server is not None and game_server.is_alive():
print("Terminate gparserame server")
print("Terminate game server")
game_server.terminate()
if pygame_gui is not None and pygame_gui.is_alive():
print("Terminate pygame gui")
......
......@@ -33,6 +33,7 @@ layout_chars:
"""
import inspect
import sys
from random import Random
from typing import Any, Type, TypeVar
import numpy as np
......@@ -50,7 +51,15 @@ from overcooked_simulator.counters import (
SinkAddon,
Trashcan,
)
from overcooked_simulator.game_items import ItemInfo, ItemType, CookingEquipment, Plate
from overcooked_simulator.effect_manager import EffectManager
from overcooked_simulator.game_items import (
ItemInfo,
ItemType,
CookingEquipment,
Plate,
Item,
)
from overcooked_simulator.hooks import Hooks
from overcooked_simulator.order import OrderAndScoreManager
from overcooked_simulator.utils import get_closest
......@@ -72,10 +81,10 @@ def convert_words_to_chars(layout_chars_config: dict[str, str]) -> dict[str, str
"""
word_refs = {
"hash": "#",
"space": " ",
# "space": " ",
"dot": ".",
"comma": ",",
"semicolon": ";",
# "semicolon": ";",
"colon": ":",
"minus": "-",
"exclamation": "!",
......@@ -89,6 +98,7 @@ def convert_words_to_chars(layout_chars_config: dict[str, str]) -> dict[str, str
"left": "<",
"pipe": "|",
"at": "@",
"wave": "~", # ~ is None / null in yaml
"ocurlybracket": "{",
"ccurlybracket": "}",
"osquarebracket": "[",
......@@ -111,6 +121,9 @@ class CounterFactory:
serving_window_additional_kwargs: dict[str, Any],
plate_config: PlateConfig,
order_and_score: OrderAndScoreManager,
effect_manager_config: dict,
hook: Hooks,
random: Random,
) -> None:
"""Constructor for the `CounterFactory` class. Set up the attributes necessary to instantiate the counters.
......@@ -140,6 +153,8 @@ class CounterFactory:
"""The plate config from the `environment_config`"""
self.order_and_score: OrderAndScoreManager = order_and_score
"""The order and score manager to pass to `ServingWindow` and the `Tashcan` which can affect the scores."""
self.effect_manager_config = effect_manager_config
"""The effect manager config to setup the effect manager based on the defined effects in the item info."""
self.no_counter_chars: set[str] = set(
c
......@@ -149,8 +164,11 @@ class CounterFactory:
"""A set of characters that represent counters for agents or free spaces."""
self.counter_classes: dict[str, Type] = dict(
inspect.getmembers(
sys.modules["overcooked_simulator.counters"], inspect.isclass
filter(
lambda k: issubclass(k[1], Counter),
inspect.getmembers(
sys.modules["overcooked_simulator.counters"], inspect.isclass
),
)
)
"""A dictionary of counter classes imported from the 'overcooked_simulator.counters' module."""
......@@ -166,11 +184,19 @@ class CounterFactory:
}
"""A dictionary mapping cooking counters to the list of equipment items associated with them."""
self.hook = hook
"""Reference to the hook manager."""
self.random = random
"""Random instance."""
def get_counter_object(self, c: str, pos: npt.NDArray[float]) -> Counter:
"""Create and returns a counter object based on the provided character and position."""
assert self.can_map(c), f"Can't map counter char {c}"
counter_class = None
if c == "@":
print("-")
if self.layout_chars_config[c] in self.item_info:
item_info = self.item_info[self.layout_chars_config[c]]
if item_info.type == ItemType.Equipment and item_info.equipment:
......@@ -185,30 +211,54 @@ class CounterFactory:
name=item_info.name,
item_info=item_info,
transitions=self.filter_item_info(
by_equipment_name=item_info.name
by_equipment_name=item_info.name,
add_effects=True,
),
),
hook=self.hook,
)
elif item_info.type == ItemType.Ingredient:
return Dispenser(pos=pos, dispensing=item_info)
return Dispenser(pos=pos, hook=self.hook, dispensing=item_info)
elif item_info.type == ItemType.Tool:
return Counter(
pos=pos,
hook=self.hook,
occupied_by=Item(name=item_info.name, item_info=item_info),
)
if counter_class is None:
counter_class = self.counter_classes[self.layout_chars_config[c]]
if self.layout_chars_config[c] in self.counter_classes:
counter_class = self.counter_classes[self.layout_chars_config[c]]
elif self.layout_chars_config[c] == "Plate":
return Counter(
pos=pos,
hook=self.hook,
occupied_by=Plate(
transitions=self.filter_item_info(
by_item_type=ItemType.Meal, add_effects=True
),
clean=True,
item_info=self.item_info[Plate.__name__],
),
)
kwargs = {
"pos": pos,
"hook": self.hook,
}
if issubclass(counter_class, (CuttingBoard, Sink)):
kwargs["transitions"] = self.filter_item_info(
by_equipment_name=counter_class.__name__
by_equipment_name=counter_class.__name__,
add_effects=True,
)
elif issubclass(counter_class, PlateDispenser):
kwargs.update(
{
"plate_transitions": self.filter_item_info(
by_item_type=ItemType.Meal
by_item_type=ItemType.Meal, add_effects=True
),
"plate_config": self.plate_config,
"dispensing": self.item_info[Plate.__name__],
"random": self.random,
}
)
elif issubclass(counter_class, ServingWindow):
......@@ -242,21 +292,32 @@ class CounterFactory:
self,
by_item_type: ItemType = None,
by_equipment_name: str = None,
add_effects: bool = False,
) -> dict[str, ItemInfo]:
"""Filter the item info dict by item type or equipment name"""
filtered = {}
if by_item_type is not None:
return {
filtered = {
name: info
for name, info in self.item_info.items()
if info.type == by_item_type
}
if by_equipment_name is not None:
return {
filtered = {
name: info
for name, info in self.item_info.items()
if info.equipment is not None
and info.equipment.name == by_equipment_name
}
if add_effects:
for name, effect in self.filter_item_info(
by_item_type=ItemType.Effect
).items():
for need in effect.needs:
if need in filtered:
filtered.update({name: effect})
if by_item_type or by_equipment_name:
return filtered
return self.item_info
def post_counter_setup(self, counters: list[Counter]):
......@@ -282,11 +343,34 @@ class CounterFactory:
counter: Sink # Pycharm type checker does now work for match statements?
assert len(sink_addons) > 0, "No SinkAddon but normal Sink"
closest_addon = get_closest(pos, sink_addons)
assert 1 - (1 * 0.05) <= np.linalg.norm(
assert 1.0 == np.linalg.norm(
closest_addon.pos - pos
), f"No SinkAddon connected to Sink at pos {pos}"
counter.set_addon(closest_addon)
def setup_effect_manger(self, counters: list[Counter]) -> dict[str, EffectManager]:
effect_manager = {}
for name, effect in self.filter_item_info(by_item_type=ItemType.Effect).items():
assert (
effect.manager in self.effect_manager_config
), f"Manager for effect not found: {name} -> {effect.manager} not in {list(self.effect_manager_config.keys())}"
if effect.manager in effect_manager:
manager = effect_manager[effect.manager]
else:
manager = self.effect_manager_config[effect.manager]["class"](
hook=self.hook,
random=self.random,
**self.effect_manager_config[effect.manager]["kwargs"],
)
manager.set_counters(counters)
effect_manager[effect.manager] = manager
manager.add_effect(effect)
effect.manager = manager
return effect_manager
@staticmethod
def get_counter_of_type(counter_type: Type[T], counters: list[Counter]) -> list[T]:
"""Filter all counters in the environment for a counter type."""
......
This diff is collapsed.
from __future__ import annotations
from collections import deque
from datetime import timedelta, datetime
from random import Random
from typing import TYPE_CHECKING, Tuple
from overcooked_simulator.game_items import (
ItemInfo,
Item,
ItemType,
Effect,
CookingEquipment,
)
from overcooked_simulator.hooks import Hooks, NEW_FIRE, FIRE_SPREADING
from overcooked_simulator.utils import get_touching_counters, find_item_on_counters
if TYPE_CHECKING:
from overcooked_simulator.counters import Counter
class EffectManager:
def __init__(self, hook: Hooks, random: Random) -> None:
self.effects = []
self.counters = []
self.hook = hook
self.new_effects: list[Tuple[Effect, Item | Counter]] = []
self.random = random
def add_effect(self, effect: ItemInfo):
self.effects.append(effect)
def set_counters(self, counters: list[Counter]):
self.counters.extend(counters)
def register_active_effect(self, effect: Effect, target: Item | Counter):
target.active_effects.append(effect)
self.new_effects.append((effect, target))
def progress(self, passed_time: timedelta, now: datetime):
...
def can_start_effect_transition(
self, effect: ItemInfo, target: Item | Counter
) -> bool:
return effect.name not in [e.name for e in target.active_effects]
def remove_active_effect(self, effect: Effect, target: Item | Counter):
...
class FireEffectManager(EffectManager):
# TODO add Random object
def __init__(
self,
spreading_duration: list[float],
fire_burns_ingredients_and_meals: bool,
**kwargs,
):
super().__init__(**kwargs)
self.spreading_duration = spreading_duration
self.fire_burns_ingredients_and_meals = fire_burns_ingredients_and_meals
self.effect_to_timer: dict[str:datetime] = {}
self.next_finished_timer = datetime.max
self.active_effects: list[Tuple[Effect, Item | Counter]] = []
def progress(self, passed_time: timedelta, now: datetime):
if self.new_effects:
for effect, target in self.new_effects:
self.effect_to_timer[effect.uuid] = now + timedelta(
seconds=self.random.uniform(*self.spreading_duration)
)
self.next_finished_timer = min(
self.next_finished_timer, self.effect_to_timer[effect.uuid]
)
self.hook(NEW_FIRE, target=target)
self.active_effects.append((effect, target))
self.new_effects = []
if self.next_finished_timer < now:
for effect, target in self.active_effects:
if self.effect_to_timer[effect.uuid] < now:
if isinstance(target, Item):
target = find_item_on_counters(target.uuid, self.counters)
if target:
touching = get_touching_counters(target, self.counters)
for counter in touching:
if counter.occupied_by:
if isinstance(counter.occupied_by, deque):
self.apply_effect(effect, counter.occupied_by[-1])
else:
self.apply_effect(effect, counter.occupied_by)
else:
self.apply_effect(effect, counter)
self.effect_to_timer[effect.uuid] = now + timedelta(
seconds=self.random.uniform(*self.spreading_duration)
)
if self.effect_to_timer:
self.next_finished_timer = min(self.effect_to_timer.values())
else:
self.next_finished_timer = datetime.max
def apply_effect(self, effect: Effect, target: Item | Counter):
if (
isinstance(target, Item)
and target.item_info.type == ItemType.Tool
and effect.name in target.item_info.needs
):
# Tools that reduce fire can not burn
return
if effect.name not in target.active_effects and target.uuid not in [
t.uuid for _, t in self.active_effects
]:
self.hook(FIRE_SPREADING, target=target)
if isinstance(target, CookingEquipment):
if target.content_list:
for content in target.content_list:
self.burn_content(content)
if self.fire_burns_ingredients_and_meals:
self.burn_content(target.content_ready)
elif isinstance(target, Item):
self.burn_content(target)
self.register_active_effect(
Effect(effect.name, item_info=effect.item_info), target
)
def burn_content(self, content: Item):
if self.fire_burns_ingredients_and_meals and content:
if not content.name.startswith("Burnt"):
content.name = "Burnt" + content.name
def remove_active_effect(self, effect: Effect, target: Item | Counter):
if (effect, target) in self.active_effects:
self.active_effects.remove((effect, target))
if effect.uuid in self.effect_to_timer:
del self.effect_to_timer[effect.uuid]
"""
# Usage
- Set `CONNECT_WITH_STUDY_SERVER` in overcooked_gui.py to True.
- Run this script. Copy the manager id that is printed
- Run the game_server.py script with the manager id copied from the terminal
```
python game_server.py --manager_ids COPIED_UUID
```
- Run 2 overcooked_gui.py scripts in different terminals. For more players change `NUMBER_PLAYER_PER_ENV` and start more guis.
The environment starts when all players connected.
"""
import argparse
import asyncio
import logging
from typing import Tuple
import requests
import uvicorn
from fastapi import FastAPI
from overcooked_simulator import ROOT_DIR
from overcooked_simulator.game_server import CreateEnvironmentConfig
from overcooked_simulator.server_results import PlayerInfo
from overcooked_simulator.utils import (
url_and_port_arguments,
add_list_of_manager_ids_arguments,
)
NUMBER_PLAYER_PER_ENV = 2
log = logging.getLogger(__name__)
app = FastAPI()
game_server_url = "localhost:8000"
server_manager_id = None
# @app.get("/")
# async def root(response_class=HTMLResponse):
# return """
# <html>
# <head>
# <title>Overcooked Game</title>
# </head>
# <body>
# <h1>Start Game!</h1>
# <button type="button">Click Me!</button>
# </body>
# </html>
# """
running_envs: dict[str, Tuple[int, dict[str, PlayerInfo], list[str]]] = {}
current_free_envs = []
@app.post("/connect_to_game/{request_id}")
async def want_to_play(request_id: str):
global current_free_envs
# TODO based on study desing / internal state of request id current state (which level to play)
if current_free_envs:
current_free_env = current_free_envs.pop()
running_envs[current_free_env][2].append(request_id)
new_running_env = (
running_envs[current_free_env][0] + 1,
running_envs[current_free_env][1],
running_envs[current_free_env][2],
)
player_info = running_envs[current_free_env][1][str(new_running_env[0])]
running_envs[current_free_env] = new_running_env
if new_running_env[0] < NUMBER_PLAYER_PER_ENV - 1:
current_free_env.append(current_free_env)
return player_info
else:
environment_config_path = ROOT_DIR / "game_content" / "environment_config.yaml"
layout_path = ROOT_DIR / "game_content" / "layouts" / "basic.layout"
item_info_path = ROOT_DIR / "game_content" / "item_info.yaml"
with open(item_info_path, "r") as file:
item_info = file.read()
with open(layout_path, "r") as file:
layout = file.read()
with open(environment_config_path, "r") as file:
environment_config = file.read()
creation_json = CreateEnvironmentConfig(
manager_id=server_manager_id,
number_players=NUMBER_PLAYER_PER_ENV,
environment_settings={"all_player_can_pause_game": False},
item_info_config=item_info,
environment_config=environment_config,
layout_config=layout,
seed=1234567890,
).model_dump(mode="json")
# todo async
env_info = requests.post(
game_server_url + "/manage/create_env/", json=creation_json
)
if env_info.status_code == 403:
raise ValueError(f"Forbidden Request: {env_info.json()['detail']}")
env_info = env_info.json()
print(env_info)
running_envs[env_info["env_id"]] = (0, env_info["player_info"], [request_id])
current_free_envs.append(env_info["env_id"])
return env_info["player_info"]["0"]
def main(host, port, game_server_url_, manager_id):
global game_server_url, server_manager_id
game_server_url = "http://" + game_server_url_
server_manager_id = manager_id[0]
print(f"Use {server_manager_id=} for {game_server_url=}")
loop = asyncio.new_event_loop()
config = uvicorn.Config(app, host=host, port=port, loop=loop)
server = uvicorn.Server(config)
loop.run_until_complete(server.serve())
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="Overcooked Simulator Study Server",
description="Study Server: Match Making, client pre and post managing.",
epilog="For further information, see https://scs.pages.ub.uni-bielefeld.de/cocosy/overcooked-simulator/overcooked_simulator.html",
)
url_and_port_arguments(parser=parser, server_name="Study Server", default_port=8080)
add_list_of_manager_ids_arguments(parser=parser)
args = parser.parse_args()
main(
args.url,
args.port,
game_server_url_="localhost:8000",
manager_id=args.manager_ids,
)
concurrency: MultiProcessing
communication:
communication_prefs:
- !name:ipaacar_com_service.communications.ipaacar_com.IPAACARInfo
modules:
connection:
module_info: !name:cocosy_agent.modules.connection_module.ConnectionModule
mean_frequency_step: 2 # 2: every 0.5 seconds
working_memory:
module_info: !name:cocosy_agent.modules.working_memory_module.WorkingMemoryModule
subtask_selection:
module_info: !name:cocosy_agent.modules.random_subtask_module.RandomSubtaskModule
action_execution:
module_info: !name:cocosy_agent.modules.action_execution_module.ActionExecutionModule
mean_frequency_step: 10 # 2: every 0.5 seconds
# gui:
# module_info: !name:aaambos.std.guis.pysimplegui.pysimplegui_window.PySimpleGUIWindowModule
# window_title: Counting GUI
# topics_to_show: [["SubtaskDecision", "cocosy_agent.conventions.communication.SubtaskDecision", ["task_type"]], ["ActionControl", "cocosy_agent.conventions.communication.ActionControl", ["action_type"]]]
status_manager:
module_info: !name:aaambos.std.modules.module_status_manager.ModuleStatusManager
gui: false
\ No newline at end of file
import argparse
import asyncio
import dataclasses
import json
import random
import time
from collections import defaultdict
from datetime import datetime, timedelta
import numpy as np
from websockets import connect
from overcooked_simulator.overcooked_environment import (
ActionType,
Action,
InterActionData,
)
from overcooked_simulator.utils import custom_asdict_factory
async def agent():
parser = argparse.ArgumentParser("Random agent")
parser.add_argument("--uri", type=str)
parser.add_argument("--player_id", type=str)
parser.add_argument("--player_hash", type=str)
parser.add_argument("--step_time", type=float, default=0.5)
args = parser.parse_args()
async with connect(args.uri) as websocket:
await websocket.send(
json.dumps({"type": "ready", "player_hash": args.player_hash})
)
await websocket.recv()
ended = False
counters = None
player_info = {}
current_agent_pos = None
interaction_counter = None
last_interacting = False
last_interact_progress = None
threshold = datetime.max
task_type = None
task_args = None
started_interaction = False
still_interacting = False
current_nearest_counter_id = None
while not ended:
time.sleep(args.step_time)
await websocket.send(
json.dumps({"type": "get_state", "player_hash": args.player_hash})
)
state = json.loads(await websocket.recv())
if counters is None:
counters = defaultdict(list)
for counter in state["counters"]:
counters[counter["type"]].append(counter)
for player in state["players"]:
if player["id"] == args.player_id:
player_info = player
current_agent_pos = player["pos"]
if player["current_nearest_counter_id"]:
if (
current_nearest_counter_id
!= player["current_nearest_counter_id"]
):
for counter in state["counters"]:
if (
counter["id"]
== player["current_nearest_counter_id"]
):
interaction_counter = counter
current_nearest_counter_id = player[
"current_nearest_counter_id"
]
break
if last_interacting:
if (
not interaction_counter
or not interaction_counter["occupied_by"]
or isinstance(interaction_counter["occupied_by"], list)
or (
interaction_counter["occupied_by"][
"progress_percentage"
]
== 1.0
)
):
last_interacting = False
last_interact_progress = None
else:
if (
interaction_counter
and interaction_counter["occupied_by"]
and not isinstance(interaction_counter["occupied_by"], list)
):
if (
last_interact_progress
!= interaction_counter["occupied_by"][
"progress_percentage"
]
):
last_interact_progress = interaction_counter[
"occupied_by"
]["progress_percentage"]
last_interacting = True
break
if task_type:
if threshold < datetime.now():
print(
args.player_hash, args.player_id, "---Threshold---Too long---"
)
task_type = None
match task_type:
case "GOTO":
diff = np.array(task_args) - np.array(current_agent_pos)
dist = np.linalg.norm(diff)
if dist > 1.2:
if dist != 0:
await websocket.send(
json.dumps(
{
"type": "action",
"action": dataclasses.asdict(
Action(
args.player_id,
ActionType.MOVEMENT,
(diff / dist).tolist(),
args.step_time + 0.01,
),
dict_factory=custom_asdict_factory,
),
"player_hash": args.player_hash,
}
)
)
await websocket.recv()
else:
task_type = None
task_args = None
case "INTERACT":
if not started_interaction or (
still_interacting and interaction_counter
):
if not started_interaction:
started_interaction = True
still_interacting = True
await websocket.send(
json.dumps(
{
"type": "action",
"action": dataclasses.asdict(
Action(
args.player_id,
ActionType.INTERACT,
InterActionData.START,
),
dict_factory=custom_asdict_factory,
),
"player_hash": args.player_hash,
}
)
)
await websocket.recv()
else:
still_interacting = False
started_interaction = False
task_type = None
task_args = None
case "PUT":
await websocket.send(
json.dumps(
{
"type": "action",
"action": dataclasses.asdict(
Action(
args.player_id,
ActionType.PUT,
"pickup",
),
dict_factory=custom_asdict_factory,
),
"player_hash": args.player_hash,
}
)
)
await websocket.recv()
task_type = None
task_args = None
case None:
...
if not task_type:
task_type = random.choice(["GOTO", "PUT", "INTERACT"])
threshold = datetime.now() + timedelta(seconds=15.0)
if task_type == "GOTO":
counter_type = random.choice(list(counters.keys()))
task_args = random.choice(counters[counter_type])["pos"]
print(args.player_hash, args.player_id, task_type, counter_type)
else:
print(args.player_hash, args.player_id, task_type)
task_args = None
ended = state["ended"]
if __name__ == "__main__":
asyncio.run(agent())
general:
agent_name: cocosy_agent
instance: _dev
local_agent_directories: ~/aaambos_agents
plus:
agent_websocket: ws://localhost:8000:/ws/player/MY_CLIENT_ID
player_hash: abcdefghijklmnopqrstuvwxyz
agent_id: 1
logging:
log_level_command_line: INFO
supervisor:
run_time_manager_class: !name:aaambos.std.supervision.instruction_run_time_manager.instruction_run_time_manager.InstructionRunTimeManager
......@@ -18,14 +18,16 @@ meals:
layout_chars:
_: Free
hash: Counter
hash: Counter # #
A: Agent
pipe: Extinguisher
P: PlateDispenser
C: CuttingBoard
X: Trashcan
W: ServingWindow
$: ServingWindow
S: Sink
+: SinkAddon
at: Plate # @ just a clean plate on a counter
U: Pot # with Stove
Q: Pan # with Stove
O: Peel # with Oven
......@@ -40,6 +42,16 @@ layout_chars:
G: Sausage # sausaGe
B: Bun
M: Meat
question: Counter # ? mushroom
: Counter
^: Counter
right: Counter
left: Counter
wave: Free # ~ Water
minus: Free # - Ice
dquote: Counter # " wall/truck
p: Counter # second plate return ??
orders:
order_gen_class: !!python/name:overcooked_simulator.order.RandomOrderGeneration ''
......@@ -83,5 +95,63 @@ orders:
player_config:
radius: 0.4
player_speed_units_per_seconds: 8
player_speed_units_per_seconds: 6
interaction_range: 1.6
restricted_view: False
view_angle: 70
view_range: 5.5 # in grid units, can be "null"
effect_manager:
FireManager:
class: !!python/name:overcooked_simulator.effect_manager.FireEffectManager ''
kwargs:
spreading_duration: [ 5, 10 ]
fire_burns_ingredients_and_meals: true
extra_setup_functions:
# json_states:
# func: !!python/name:overcooked_simulator.recording.class_recording_with_hooks ''
# kwargs:
# hooks: [ json_state ]
# log_class: !!python/name:overcooked_simulator.recording.LogRecorder ''
# log_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
actions:
func: !!python/name:overcooked_simulator.recording.class_recording_with_hooks ''
kwargs:
hooks: [ pre_perform_action ]
log_class: !!python/name:overcooked_simulator.recording.LogRecorder ''
log_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
random_env_events:
func: !!python/name:overcooked_simulator.recording.class_recording_with_hooks ''
kwargs:
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
log_class: !!python/name:overcooked_simulator.recording.LogRecorder ''
log_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
env_configs:
func: !!python/name:overcooked_simulator.recording.class_recording_with_hooks ''
kwargs:
hooks: [ env_initialized, item_info_config ]
log_class: !!python/name:overcooked_simulator.recording.LogRecorder ''
log_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
# info_msg:
# func: !!python/name:overcooked_simulator.recording.class_recording_with_hooks ''
# kwargs:
# hooks: [ cutting_board_100 ]
# log_class: !!python/name:overcooked_simulator.info_msg.InfoMsgManager ''
# log_class_kwargs:
# msg: Glückwunsch du hast was geschnitten!
# fire_msg:
# func: !!python/name:overcooked_simulator.recording.class_recording_with_hooks ''
# kwargs:
# hooks: [ new_fire ]
# log_class: !!python/name:overcooked_simulator.info_msg.InfoMsgManager ''
# log_class_kwargs:
# msg: Feuer, Feuer, Feuer
# level: Warning
\ No newline at end of file
......@@ -176,3 +176,57 @@ Pizza:
needs: [ PizzaBase, ChoppedTomato, GratedCheese, ChoppedSausage ]
seconds: 7.0
equipment: Peel
# --------------------------------------------------------------------------------
BurntCookedPatty:
type: Waste
seconds: 5.0
needs: [ CookedPatty ]
equipment: Pan
BurntChips:
type: Waste
seconds: 5.0
needs: [ Chips ]
equipment: Basket
BurntFriedFish:
type: Waste
seconds: 5.0
needs: [ FriedFish ]
equipment: Basket
BurntTomatoSoup:
type: Waste
needs: [ TomatoSoup ]
seconds: 6.0
equipment: Pot
BurntOnionSoup:
type: Waste
needs: [ OnionSoup ]
seconds: 6.0
equipment: Pot
BurntPizza:
type: Waste
needs: [ Pizza ]
seconds: 7.0
equipment: Peel
# --------------------------------------------------------------------------------
Fire:
type: Effect
seconds: 5.0
needs: [ BurntCookedPatty, BurntChips, BurntFriedFish, BurntTomatoSoup, BurntOnionSoup, BurntPizza ]
manager: FireManager
effect_type: Unusable
# --------------------------------------------------------------------------------
Extinguisher:
type: Tool
seconds: 1.0
needs: [ Fire ]
......@@ -177,3 +177,57 @@ Pizza:
needs: [ PizzaBase, ChoppedTomato, GratedCheese, ChoppedSausage ]
seconds: 0.1
equipment: Peel
# --------------------------------------------------------------------------------
BurntCookedPatty:
type: Waste
seconds: 5.0
needs: [ CookedPatty ]
equipment: Pan
BurntChips:
type: Waste
seconds: 1.0
needs: [ Chips ]
equipment: Basket
BurntFriedFish:
type: Waste
seconds: 5.0
needs: [ FriedFish ]
equipment: Basket
BurntTomatoSoup:
type: Waste
needs: [ TomatoSoup ]
seconds: 6.0
equipment: Pot
BurntOnionSoup:
type: Waste
needs: [ OnionSoup ]
seconds: 6.0
equipment: Pot
BurntPizza:
type: Waste
needs: [ Pizza ]
seconds: 7.0
equipment: Peel
# --------------------------------------------------------------------------------
Fire:
type: Effect
seconds: 1.0
needs: [ BurntCookedPatty, BurntChips, BurntFriedFish, BurntTomatoSoup, BurntOnionSoup, BurntPizza ]
manager: FireManager
effect_type: Unusable
# --------------------------------------------------------------------------------
Extinguisher:
type: Tool
seconds: 0.1
needs: [ Fire ]
\ No newline at end of file
#QU#FO#TNLB#
#__________M
#__________K
W__________I
|__________K
$__________I
#__A_____A_D
C__________E
C__________G
......
______
______
______
______
______
______
_____P
\ No newline at end of file
_______
_______
_______
_______
__A____
_______
_______
______P
\ No newline at end of file
#QU#F###O#T#################N###L###B#
#____________________________________#
#____________________________________M
#____________________________________#
#____________________________________#
#____________________________________K
$____________________________________I
#____________________________________#
#____________________________________#
#__A_____A___________________________D
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
C____________________________________E
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
C____________________________________G
#____________________________________#
#P#####S+####X#####S+#################
\ No newline at end of file
#QU#F###O#T#################N###L###B#
#____________________________________#
#____________________________________M
#____________________________________#
#____________________________________#
#____________________________________K
W____________________________________I
#____________________________________#
#____________________________________#
#__A_____A___________________________D
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
C____________________________________E
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
#____________________________________#
C____________________________________G
#____________________________________#
#P#####S+####X#####S+#################
\ No newline at end of file
###N####U####
#___________|
#___A___A___#
#___________S
##########__+
P___________#
$___________#
$___________X
###C#C###@@##
; seconds=150
; plates={c:0, d:0}
; dirty_plates=true
; link: https://overcooked.fandom.com/wiki/1-1_(Overcooked!)
\ No newline at end of file
_##U#U#__###|X_#
______#____A___$
+_____@__@_____$
S________#_____P
____A____#______
_##C#C#__#T#N##_
; seconds=240
; plates={c:0, d:0}
; dirty_plates=true
; link: https://overcooked.fandom.com/wiki/1-2_(Overcooked!)
; pedestrians: down the middle road
_____________
___U#U##$$P|_
_#____#______
_@__A_#___A__
_@____#______
_@____#______
_X____#______
_#C#C##NT?___
_____________
; seconds=240
; plates={c:0, d:0}
; dirty_plates=false
; link: https://overcooked.fandom.com/wiki/1-3_(Overcooked!)
; moving counters
\ No newline at end of file
##S+####QQQQ#
T____###____|
M_A__###__A_#
B___________#
L____###____$
#____###____$
#____###____P
X____###____@
##C#C###@@@@#
; seconds=240
; plates={c:0, d:0}
; dirty_plates=true
; link: https://overcooked.fandom.com/wiki/1-4_(Overcooked!)
\ No newline at end of file
#####P$$|#####
#?NT#A_A_#S+##
#____________X
#_##########_#
#_##########_#
#_##########_#
#_#######@@@_#
#____________#
#C#C####U#U#U#
; seconds=240
; plates={c:0, d:0}
; dirty_plates=true
; link: https://overcooked.fandom.com/wiki/1-5_(Overcooked!)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment