From 8d6dcd70ae9f681dd36d45401ba6f37bd6eed657 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Thu, 19 Oct 2023 17:25:31 +0200 Subject: [PATCH 01/12] WIP: object, entity rework --- .../environment/entity/entity.py | 90 +++++++++++++++++-- .../environment/entity/object.py | 21 +++++ marl_factory_grid/environment/entity/util.py | 2 +- .../environment/entity/wall_floor.py | 3 +- .../environment/groups/agents.py | 4 +- .../environment/groups/env_objects.py | 29 ++++-- .../environment/groups/mixins.py | 9 -- marl_factory_grid/environment/groups/utils.py | 6 +- .../environment/groups/wall_n_floors.py | 4 +- .../modules/batteries/entitites.py | 4 +- marl_factory_grid/modules/batteries/groups.py | 6 +- marl_factory_grid/modules/clean_up/groups.py | 4 +- .../modules/destinations/groups.py | 4 +- marl_factory_grid/modules/doors/entitites.py | 2 +- marl_factory_grid/modules/doors/groups.py | 4 +- marl_factory_grid/modules/items/groups.py | 8 +- marl_factory_grid/modules/machines/groups.py | 4 +- .../modules/maintenance/groups.py | 4 +- 18 files changed, 155 insertions(+), 53 deletions(-) diff --git a/marl_factory_grid/environment/entity/entity.py b/marl_factory_grid/environment/entity/entity.py index 67bf665..8ace59d 100644 --- a/marl_factory_grid/environment/entity/entity.py +++ b/marl_factory_grid/environment/entity/entity.py @@ -1,21 +1,57 @@ import abc +from collections import defaultdict +from .object import Object from .. import constants as c -from .object import EnvObject from ...utils.render import RenderEntity from ...utils.results import ActionResult -class Entity(EnvObject, abc.ABC): +class Entity(Object, abc.ABC): """Full Env Entity that lives on the environment Grid. Doors, Items, DirtPile etc...""" + _u_idx = defaultdict(lambda: 0) + @property def state(self): return self._status or ActionResult(entity=self, identifier=c.NOOP, validity=c.VALID, reward=0) + # @property + # def var_has_position(self): + # return self.pos != c.VALUE_NO_POS + var_has_position: bool = True + @property - def var_has_position(self): - return self.pos != c.VALUE_NO_POS + def var_is_blocking_light(self): + try: + return self._collection.var_is_blocking_light or False + except AttributeError: + return False + + # var_is_blocking_light: bool = True + + @property + def var_can_move(self): + try: + return self._collection.var_can_move or False + except AttributeError: + return False + + @property + def var_is_blocking_pos(self): + try: + return self._collection.var_is_blocking_pos or False + except AttributeError: + return False + + @property + def var_can_collide(self): + try: + return self._collection.var_can_collide or False + except AttributeError: + return False + + # var_can_collide: bool = True @property def x(self): @@ -29,10 +65,6 @@ class Entity(EnvObject, abc.ABC): def pos(self): return self._pos - @property - def tile(self): - return self._tile # wall_n_floors funktionalität - # @property # def last_tile(self): # try: @@ -71,7 +103,7 @@ class Entity(EnvObject, abc.ABC): print(f'Objects of {self.__class__.__name__} can not be bound to other entities.') exit() - def summarize_state(self) -> dict: # tile=str(self.tile.name) + def summarize_state(self) -> dict: return dict(name=str(self.name), x=int(self.x), y=int(self.y), can_collide=bool(self.var_can_collide)) @abc.abstractmethod @@ -80,3 +112,43 @@ class Entity(EnvObject, abc.ABC): def __repr__(self): return super(Entity, self).__repr__() + f'(@{self.pos})' + + @property + def obs_tag(self): + try: + return self._collection.name or self.name + except AttributeError: + return self.name + + @property + def encoding(self): + return c.VALUE_OCCUPIED_CELL + + def change_parent_collection(self, other_collection): + other_collection.add_item(self) + self._collection.delete_env_object(self) + self._collection = other_collection + return self._collection == other_collection + + @classmethod + def from_coordinates(cls, positions: [(int, int)], *args, entity_kwargs=None, **kwargs, ): + collection = cls(*args, **kwargs) + collection.add_items( + [cls._entity(tuple(pos), **entity_kwargs if entity_kwargs is not None else {}) for pos in positions]) + return collection + + def notify_del_entity(self, entity): + try: + self.pos_dict[entity.pos].remove(entity) + except (ValueError, AttributeError): + pass + + def by_pos(self, pos: (int, int)): + pos = tuple(pos) + try: + return self.state.entities.pos_dict[pos] + # return next(e for e in self if e.pos == pos) + except StopIteration: + pass + except ValueError: + print() diff --git a/marl_factory_grid/environment/entity/object.py b/marl_factory_grid/environment/entity/object.py index 1e023b6..0cf1591 100644 --- a/marl_factory_grid/environment/entity/object.py +++ b/marl_factory_grid/environment/entity/object.py @@ -12,6 +12,19 @@ class Object: def __bool__(self): return True + @property + def var_has_position(self): # brauchen wir das hier jetzt? + try: + return self.pos != c.VALUE_NO_POS or False + except AttributeError: + return False + + @property + def var_can_be_bound(self): + try: + return self._collection.var_can_be_bound or False + except AttributeError: + return False @property def observers(self): @@ -70,6 +83,14 @@ class Object: def summarize_state(self): return dict() + def bind(self, entity): + # noinspection PyAttributeOutsideInit + self._bound_entity = entity + return c.VALID + + def belongs_to_entity(self, entity): + return self._bound_entity == entity + class EnvObject(Object): diff --git a/marl_factory_grid/environment/entity/util.py b/marl_factory_grid/environment/entity/util.py index fbf0c4a..bf3866e 100644 --- a/marl_factory_grid/environment/entity/util.py +++ b/marl_factory_grid/environment/entity/util.py @@ -30,7 +30,7 @@ class PlaceHolder(Object): return "PlaceHolder" -class GlobalPosition(BoundEntityMixin, EnvObject): +class GlobalPosition(Object): @property def encoding(self): diff --git a/marl_factory_grid/environment/entity/wall_floor.py b/marl_factory_grid/environment/entity/wall_floor.py index c5bb09a..1c7be6c 100644 --- a/marl_factory_grid/environment/entity/wall_floor.py +++ b/marl_factory_grid/environment/entity/wall_floor.py @@ -3,6 +3,7 @@ from typing import List import numpy as np from marl_factory_grid.environment import constants as c +from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment.entity.object import EnvObject from marl_factory_grid.utils.render import RenderEntity from marl_factory_grid.utils import helpers as h @@ -109,7 +110,7 @@ class Floor(EnvObject): return None -class Wall(Floor): +class Wall(Entity): @property def var_can_collide(self): diff --git a/marl_factory_grid/environment/groups/agents.py b/marl_factory_grid/environment/groups/agents.py index 0169f88..5c70e54 100644 --- a/marl_factory_grid/environment/groups/agents.py +++ b/marl_factory_grid/environment/groups/agents.py @@ -1,9 +1,9 @@ from marl_factory_grid.environment.entity.agent import Agent -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin -class Agents(PositionMixin, EnvObjects): +class Agents(PositionMixin, Collection): _entity = Agent is_blocking_light = False can_move = True diff --git a/marl_factory_grid/environment/groups/env_objects.py b/marl_factory_grid/environment/groups/env_objects.py index 1113833..65a3b45 100644 --- a/marl_factory_grid/environment/groups/env_objects.py +++ b/marl_factory_grid/environment/groups/env_objects.py @@ -2,26 +2,27 @@ from marl_factory_grid.environment.groups.objects import Objects from marl_factory_grid.environment.entity.object import EnvObject -class EnvObjects(Objects): - +class Collection(Objects): _entity = EnvObject var_is_blocking_light: bool = False var_can_collide: bool = False - var_has_position: bool = False var_can_move: bool = False - var_can_be_bound: bool = False + + var_has_position: bool = False # alles was posmixin hat true + var_has_bound = False # batteries, globalpos, inventories true + var_can_be_bound: bool = False # == ^ @property def encodings(self): return [x.encoding for x in self] def __init__(self, size, *args, **kwargs): - super(EnvObjects, self).__init__(*args, **kwargs) + super(Collection, self).__init__(*args, **kwargs) self.size = size def add_item(self, item: EnvObject): assert self.var_has_position or (len(self) <= self.size) - super(EnvObjects, self).add_item(item) + super(Collection, self).add_item(item) return self def delete_env_object(self, env_object: EnvObject): @@ -29,3 +30,19 @@ class EnvObjects(Objects): def delete_env_object_by_name(self, name): del self[name] + + @property + def obs_pairs(self): + return [(x.name, x) for x in self] + + def by_entity(self, entity): + try: + return next((x for x in self if x.belongs_to_entity(entity))) + except (StopIteration, AttributeError): + return None + + def idx_by_entity(self, entity): + try: + return next((idx for idx, x in enumerate(self) if x.belongs_to_entity(entity))) + except (StopIteration, AttributeError): + return None diff --git a/marl_factory_grid/environment/groups/mixins.py b/marl_factory_grid/environment/groups/mixins.py index 34bab16..d62af20 100644 --- a/marl_factory_grid/environment/groups/mixins.py +++ b/marl_factory_grid/environment/groups/mixins.py @@ -19,15 +19,6 @@ class PositionMixin: def render(self): return [y for y in [x.render() for x in self] if y is not None] - # @classmethod - # def from_tiles(cls, tiles, *args, entity_kwargs=None, **kwargs): - # collection = cls(*args, **kwargs) - # entities = [cls._entity(tile, str_ident=i, - # **entity_kwargs if entity_kwargs is not None else {}) - # for i, tile in enumerate(tiles)] - # collection.add_items(entities) - # return collection - @classmethod def from_coordinates(cls, positions: [(int, int)], *args, entity_kwargs=None, **kwargs, ): collection = cls(*args, **kwargs) diff --git a/marl_factory_grid/environment/groups/utils.py b/marl_factory_grid/environment/groups/utils.py index a3f90b0..4c46bbe 100644 --- a/marl_factory_grid/environment/groups/utils.py +++ b/marl_factory_grid/environment/groups/utils.py @@ -3,7 +3,7 @@ from typing import List, Union import numpy as np from marl_factory_grid.environment.entity.util import GlobalPosition -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin from marl_factory_grid.environment.groups.objects import Objects from marl_factory_grid.modules.zones import Zone @@ -11,7 +11,7 @@ from marl_factory_grid.utils import helpers as h from marl_factory_grid.environment import constants as c -class Combined(PositionMixin, EnvObjects): +class Combined(PositionMixin, Collection): @property def name(self): @@ -35,7 +35,7 @@ class Combined(PositionMixin, EnvObjects): return [(name, None) for name in self.names] -class GlobalPositions(HasBoundMixin, EnvObjects): +class GlobalPositions(Collection): _entity = GlobalPosition is_blocking_light = False, diff --git a/marl_factory_grid/environment/groups/wall_n_floors.py b/marl_factory_grid/environment/groups/wall_n_floors.py index ffeb033..6a17f72 100644 --- a/marl_factory_grid/environment/groups/wall_n_floors.py +++ b/marl_factory_grid/environment/groups/wall_n_floors.py @@ -2,12 +2,12 @@ import random from typing import List, Tuple from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.environment.entity.wall_floor import Wall, Floor -class Walls(PositionMixin, EnvObjects): +class Walls(PositionMixin, Collection): _entity = Wall symbol = c.SYMBOL_WALL diff --git a/marl_factory_grid/modules/batteries/entitites.py b/marl_factory_grid/modules/batteries/entitites.py index fd8f40a..f7238cf 100644 --- a/marl_factory_grid/modules/batteries/entitites.py +++ b/marl_factory_grid/modules/batteries/entitites.py @@ -1,5 +1,5 @@ from marl_factory_grid.environment.entity.mixin import BoundEntityMixin -from marl_factory_grid.environment.entity.object import EnvObject +from marl_factory_grid.environment.entity.object import EnvObject, Object from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment import constants as c from marl_factory_grid.utils.render import RenderEntity @@ -7,7 +7,7 @@ from marl_factory_grid.utils.render import RenderEntity from marl_factory_grid.modules.batteries import constants as b -class Battery(BoundEntityMixin, EnvObject): +class Battery(Object): @property def is_discharged(self): diff --git a/marl_factory_grid/modules/batteries/groups.py b/marl_factory_grid/modules/batteries/groups.py index ac51daf..0995605 100644 --- a/marl_factory_grid/modules/batteries/groups.py +++ b/marl_factory_grid/modules/batteries/groups.py @@ -1,9 +1,9 @@ -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin from marl_factory_grid.modules.batteries.entitites import Pod, Battery -class Batteries(HasBoundMixin, EnvObjects): +class Batteries(Collection): _entity = Battery is_blocking_light: bool = False @@ -21,7 +21,7 @@ class Batteries(HasBoundMixin, EnvObjects): self.add_items(batteries) -class ChargePods(PositionMixin, EnvObjects): +class ChargePods(PositionMixin, Collection): _entity = Pod diff --git a/marl_factory_grid/modules/clean_up/groups.py b/marl_factory_grid/modules/clean_up/groups.py index ad24bd7..70b5bdf 100644 --- a/marl_factory_grid/modules/clean_up/groups.py +++ b/marl_factory_grid/modules/clean_up/groups.py @@ -1,4 +1,4 @@ -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.environment.entity.wall_floor import Floor from marl_factory_grid.modules.clean_up.entitites import DirtPile @@ -6,7 +6,7 @@ from marl_factory_grid.modules.clean_up.entitites import DirtPile from marl_factory_grid.environment import constants as c -class DirtPiles(PositionMixin, EnvObjects): +class DirtPiles(PositionMixin, Collection): _entity = DirtPile is_blocking_light: bool = False can_collide: bool = False diff --git a/marl_factory_grid/modules/destinations/groups.py b/marl_factory_grid/modules/destinations/groups.py index a220c04..e188461 100644 --- a/marl_factory_grid/modules/destinations/groups.py +++ b/marl_factory_grid/modules/destinations/groups.py @@ -1,11 +1,11 @@ -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.destinations.entitites import Destination from marl_factory_grid.environment import constants as c from marl_factory_grid.modules.destinations import constants as d -class Destinations(PositionMixin, EnvObjects): +class Destinations(PositionMixin, Collection): _entity = Destination is_blocking_light: bool = False can_collide: bool = False diff --git a/marl_factory_grid/modules/doors/entitites.py b/marl_factory_grid/modules/doors/entitites.py index 6f386ca..46ea350 100644 --- a/marl_factory_grid/modules/doors/entitites.py +++ b/marl_factory_grid/modules/doors/entitites.py @@ -51,7 +51,7 @@ class Door(Entity): else: self._close() if indicate_area: - self._collection.add_items([DoorIndicator(x) for x in self.tile.neighboring_floor]) + self._collection.add_items([DoorIndicator(x) for x in self.state.entities.neighboring_positions(self.pos)]) def summarize_state(self): state_dict = super().summarize_state() diff --git a/marl_factory_grid/modules/doors/groups.py b/marl_factory_grid/modules/doors/groups.py index 4a947f8..df16693 100644 --- a/marl_factory_grid/modules/doors/groups.py +++ b/marl_factory_grid/modules/doors/groups.py @@ -1,12 +1,12 @@ from typing import Union -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.doors import constants as d from marl_factory_grid.modules.doors.entitites import Door -class Doors(PositionMixin, EnvObjects): +class Doors(PositionMixin, Collection): symbol = d.SYMBOL_DOOR _entity = Door diff --git a/marl_factory_grid/modules/items/groups.py b/marl_factory_grid/modules/items/groups.py index 6f5adc0..6309a64 100644 --- a/marl_factory_grid/modules/items/groups.py +++ b/marl_factory_grid/modules/items/groups.py @@ -1,14 +1,14 @@ from marl_factory_grid.modules.items import constants as i from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.objects import Objects from marl_factory_grid.environment.groups.mixins import PositionMixin, IsBoundMixin, HasBoundMixin from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.modules.items.entitites import Item, DropOffLocation -class Items(PositionMixin, EnvObjects): +class Items(PositionMixin, Collection): _entity = Item is_blocking_light: bool = False can_collide: bool = False @@ -28,7 +28,7 @@ class Items(PositionMixin, EnvObjects): return 0 -class Inventory(IsBoundMixin, EnvObjects): +class Inventory(IsBoundMixin, Collection): _accepted_objects = Item @property @@ -90,7 +90,7 @@ class Inventories(HasBoundMixin, Objects): state[i.INVENTORY].spawn(state[c.AGENT]) -class DropOffLocations(PositionMixin, EnvObjects): +class DropOffLocations(PositionMixin, Collection): _entity = DropOffLocation is_blocking_light: bool = False can_collide: bool = False diff --git a/marl_factory_grid/modules/machines/groups.py b/marl_factory_grid/modules/machines/groups.py index f8a27e7..ed854a7 100644 --- a/marl_factory_grid/modules/machines/groups.py +++ b/marl_factory_grid/modules/machines/groups.py @@ -1,10 +1,10 @@ -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from .entitites import Machine -class Machines(PositionMixin, EnvObjects): +class Machines(PositionMixin, Collection): _entity = Machine is_blocking_light: bool = False diff --git a/marl_factory_grid/modules/maintenance/groups.py b/marl_factory_grid/modules/maintenance/groups.py index 4a32a2b..991071a 100644 --- a/marl_factory_grid/modules/maintenance/groups.py +++ b/marl_factory_grid/modules/maintenance/groups.py @@ -2,7 +2,7 @@ from typing import List from .entities import Maintainer from marl_factory_grid.environment.entity.wall_floor import Floor -from marl_factory_grid.environment.groups.env_objects import EnvObjects +from marl_factory_grid.environment.groups.env_objects import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from ..machines.actions import MachineAction from ...utils.states import Gamestate @@ -10,7 +10,7 @@ from ...utils.states import Gamestate from ..machines import constants as mc -class Maintainers(PositionMixin, EnvObjects): +class Maintainers(PositionMixin, Collection): _entity = Maintainer var_can_collide = True From d3147b9ff6f9db0bdf2e1c85d848833e9ab55027 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Fri, 20 Oct 2023 15:11:35 +0200 Subject: [PATCH 02/12] WIP: collection, entities, objects --- .../environment/entity/entity.py | 9 ++--- .../environment/entity/object.py | 5 ++- .../environment/groups/agents.py | 2 +- .../groups/{env_objects.py => collection.py} | 0 marl_factory_grid/environment/groups/utils.py | 2 +- .../environment/groups/wall_n_floors.py | 2 +- .../modules/batteries/entitites.py | 7 +++- marl_factory_grid/modules/batteries/groups.py | 2 +- marl_factory_grid/modules/clean_up/groups.py | 2 +- .../modules/destinations/entitites.py | 34 ++++++++++++++----- .../modules/destinations/groups.py | 2 +- marl_factory_grid/modules/doors/groups.py | 2 +- marl_factory_grid/modules/items/entitites.py | 6 ++-- marl_factory_grid/modules/items/groups.py | 30 ++++++++++++---- marl_factory_grid/modules/machines/groups.py | 2 +- .../modules/maintenance/groups.py | 2 +- 16 files changed, 73 insertions(+), 36 deletions(-) rename marl_factory_grid/environment/groups/{env_objects.py => collection.py} (100%) diff --git a/marl_factory_grid/environment/entity/entity.py b/marl_factory_grid/environment/entity/entity.py index 8ace59d..816b86f 100644 --- a/marl_factory_grid/environment/entity/entity.py +++ b/marl_factory_grid/environment/entity/entity.py @@ -16,10 +16,9 @@ class Entity(Object, abc.ABC): def state(self): return self._status or ActionResult(entity=self, identifier=c.NOOP, validity=c.VALID, reward=0) - # @property - # def var_has_position(self): - # return self.pos != c.VALUE_NO_POS - var_has_position: bool = True + @property + def var_has_position(self): + return self.pos != c.VALUE_NO_POS @property def var_is_blocking_light(self): @@ -28,7 +27,6 @@ class Entity(Object, abc.ABC): except AttributeError: return False - # var_is_blocking_light: bool = True @property def var_can_move(self): @@ -51,7 +49,6 @@ class Entity(Object, abc.ABC): except AttributeError: return False - # var_can_collide: bool = True @property def x(self): diff --git a/marl_factory_grid/environment/entity/object.py b/marl_factory_grid/environment/entity/object.py index 0cf1591..8596327 100644 --- a/marl_factory_grid/environment/entity/object.py +++ b/marl_factory_grid/environment/entity/object.py @@ -5,13 +5,13 @@ from marl_factory_grid.environment import constants as c class Object: - """Generell Objects for Organisation and Maintanance such as Actions etc...""" _u_idx = defaultdict(lambda: 0) def __bool__(self): return True + @property def var_has_position(self): # brauchen wir das hier jetzt? try: @@ -93,11 +93,10 @@ class Object: class EnvObject(Object): - """Objects that hold Information that are observable, but have no position on the environment grid. Inventories etc...""" _u_idx = defaultdict(lambda: 0) - + @property def obs_tag(self): try: diff --git a/marl_factory_grid/environment/groups/agents.py b/marl_factory_grid/environment/groups/agents.py index 5c70e54..571816e 100644 --- a/marl_factory_grid/environment/groups/agents.py +++ b/marl_factory_grid/environment/groups/agents.py @@ -1,5 +1,5 @@ from marl_factory_grid.environment.entity.agent import Agent -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin diff --git a/marl_factory_grid/environment/groups/env_objects.py b/marl_factory_grid/environment/groups/collection.py similarity index 100% rename from marl_factory_grid/environment/groups/env_objects.py rename to marl_factory_grid/environment/groups/collection.py diff --git a/marl_factory_grid/environment/groups/utils.py b/marl_factory_grid/environment/groups/utils.py index 4c46bbe..542db1c 100644 --- a/marl_factory_grid/environment/groups/utils.py +++ b/marl_factory_grid/environment/groups/utils.py @@ -3,7 +3,7 @@ from typing import List, Union import numpy as np from marl_factory_grid.environment.entity.util import GlobalPosition -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin from marl_factory_grid.environment.groups.objects import Objects from marl_factory_grid.modules.zones import Zone diff --git a/marl_factory_grid/environment/groups/wall_n_floors.py b/marl_factory_grid/environment/groups/wall_n_floors.py index 6a17f72..50f0a88 100644 --- a/marl_factory_grid/environment/groups/wall_n_floors.py +++ b/marl_factory_grid/environment/groups/wall_n_floors.py @@ -2,7 +2,7 @@ import random from typing import List, Tuple from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.environment.entity.wall_floor import Wall, Floor diff --git a/marl_factory_grid/modules/batteries/entitites.py b/marl_factory_grid/modules/batteries/entitites.py index f7238cf..218515f 100644 --- a/marl_factory_grid/modules/batteries/entitites.py +++ b/marl_factory_grid/modules/batteries/entitites.py @@ -9,6 +9,10 @@ from marl_factory_grid.modules.batteries import constants as b class Battery(Object): + @property + def var_can_be_bound(self): + return True + @property def is_discharged(self): return self.charge_level == 0 @@ -67,7 +71,8 @@ class Pod(Entity): if battery.charge_level == 1.0: return c.NOT_VALID # if sum(guest for guest in self.tile.guests if 'agent' in guest.name.lower()) > 1: - if sum(1 for key, val in self.state.entities.pos_dict[self.pos] for guest in val if 'agent' in guest.name.lower()) > 1: + if sum(1 for key, val in self.state.entities.pos_dict[self.pos] for guest in val if + 'agent' in guest.name.lower()) > 1: return c.NOT_VALID valid = battery.do_charge_action(self.charge_rate) return valid diff --git a/marl_factory_grid/modules/batteries/groups.py b/marl_factory_grid/modules/batteries/groups.py index 0995605..90d1fa9 100644 --- a/marl_factory_grid/modules/batteries/groups.py +++ b/marl_factory_grid/modules/batteries/groups.py @@ -1,4 +1,4 @@ -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin from marl_factory_grid.modules.batteries.entitites import Pod, Battery diff --git a/marl_factory_grid/modules/clean_up/groups.py b/marl_factory_grid/modules/clean_up/groups.py index 70b5bdf..8e93b1e 100644 --- a/marl_factory_grid/modules/clean_up/groups.py +++ b/marl_factory_grid/modules/clean_up/groups.py @@ -1,4 +1,4 @@ -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.environment.entity.wall_floor import Floor from marl_factory_grid.modules.clean_up.entitites import DirtPile diff --git a/marl_factory_grid/modules/destinations/entitites.py b/marl_factory_grid/modules/destinations/entitites.py index 99cd2c4..b8e7415 100644 --- a/marl_factory_grid/modules/destinations/entitites.py +++ b/marl_factory_grid/modules/destinations/entitites.py @@ -8,14 +8,31 @@ from marl_factory_grid.utils.render import RenderEntity from marl_factory_grid.modules.destinations import constants as d -class Destination(BoundEntityMixin, Entity): +class Destination(Entity): - var_can_move = False - var_can_collide = False - var_has_position = True - var_is_blocking_pos = False - var_is_blocking_light = False - var_can_be_bound = True # Introduce this globally! + @property + def var_can_move(self): + return False + + @property + def var_can_collide(self): + return False + + @property + def var_has_position(self): + return True + + @property + def var_is_blocking_pos(self): + return False + + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_be_bound(self): + return True @property def was_reached(self): @@ -39,7 +56,8 @@ class Destination(BoundEntityMixin, Entity): def has_just_been_reached(self): if self.was_reached: return False - agent_at_position = any(c.AGENT.lower() in x.name.lower() for x in state.entities.pos_dict[self.pos] if x.var_can_collide) + agent_at_position = any( + c.AGENT.lower() in x.name.lower() for x in state.entities.pos_dict[self.pos] if x.var_can_collide) if self.bound_entity: return ((agent_at_position and not self.action_counts) diff --git a/marl_factory_grid/modules/destinations/groups.py b/marl_factory_grid/modules/destinations/groups.py index e188461..4c6e0b9 100644 --- a/marl_factory_grid/modules/destinations/groups.py +++ b/marl_factory_grid/modules/destinations/groups.py @@ -1,4 +1,4 @@ -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.destinations.entitites import Destination from marl_factory_grid.environment import constants as c diff --git a/marl_factory_grid/modules/doors/groups.py b/marl_factory_grid/modules/doors/groups.py index df16693..3cd9307 100644 --- a/marl_factory_grid/modules/doors/groups.py +++ b/marl_factory_grid/modules/doors/groups.py @@ -1,6 +1,6 @@ from typing import Union -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.doors import constants as d from marl_factory_grid.modules.doors.entitites import Door diff --git a/marl_factory_grid/modules/items/entitites.py b/marl_factory_grid/modules/items/entitites.py index 4372d3a..0da7a03 100644 --- a/marl_factory_grid/modules/items/entitites.py +++ b/marl_factory_grid/modules/items/entitites.py @@ -8,7 +8,9 @@ from marl_factory_grid.modules.items import constants as i class Item(Entity): - var_can_collide = False + @property + def var_can_collide(self): + return False def render(self): return RenderEntity(i.ITEM, self.pos) if self.pos != c.VALUE_NO_POS else None @@ -71,7 +73,7 @@ class DropOffLocation(Entity): def place_item(self, item: Item): if self.is_full: raise RuntimeWarning("There is currently no way to clear the storage or make it unfull.") - return bc.NOT_VALID + return bc.NOT_VALID # in Zeile 81 verschieben? else: self.storage.append(item) item.set_auto_despawn(self.auto_item_despawn_interval) diff --git a/marl_factory_grid/modules/items/groups.py b/marl_factory_grid/modules/items/groups.py index 6309a64..e2a6756 100644 --- a/marl_factory_grid/modules/items/groups.py +++ b/marl_factory_grid/modules/items/groups.py @@ -1,7 +1,7 @@ from marl_factory_grid.modules.items import constants as i from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.objects import Objects from marl_factory_grid.environment.groups.mixins import PositionMixin, IsBoundMixin, HasBoundMixin from marl_factory_grid.environment.entity.agent import Agent @@ -10,8 +10,14 @@ from marl_factory_grid.modules.items.entitites import Item, DropOffLocation class Items(PositionMixin, Collection): _entity = Item - is_blocking_light: bool = False - can_collide: bool = False + + @property + def is_blocking_light(self): + return False + + @property + def can_collide(self): + return False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -21,7 +27,8 @@ class Items(PositionMixin, Collection): if item_to_spawns := max(0, (n_items - len(state[i.ITEM]))): floor_list = state.entities.floorlist[:item_to_spawns] state[i.ITEM].spawn(floor_list) - state.print(f'{item_to_spawns} new items have been spawned; next spawn in {spawn_frequency}') # spawn in self._next_item_spawn ? + state.print( + f'{item_to_spawns} new items have been spawned; next spawn in {spawn_frequency}') # spawn in self._next_item_spawn ? return len(floor_list) else: state.print('No Items are spawning, limit is reached.') @@ -57,7 +64,10 @@ class Inventory(IsBoundMixin, Collection): class Inventories(HasBoundMixin, Objects): _entity = Inventory - var_can_move = False + + @property + def var_can_move(self): + return False def __init__(self, size: int, *args, **kwargs): super(Inventories, self).__init__(*args, **kwargs) @@ -92,8 +102,14 @@ class Inventories(HasBoundMixin, Objects): class DropOffLocations(PositionMixin, Collection): _entity = DropOffLocation - is_blocking_light: bool = False - can_collide: bool = False + + @property + def is_blocking_light(self): + return False + + @property + def can_collide(self): + return False def __init__(self, *args, **kwargs): super(DropOffLocations, self).__init__(*args, **kwargs) diff --git a/marl_factory_grid/modules/machines/groups.py b/marl_factory_grid/modules/machines/groups.py index ed854a7..7d71617 100644 --- a/marl_factory_grid/modules/machines/groups.py +++ b/marl_factory_grid/modules/machines/groups.py @@ -1,4 +1,4 @@ -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from .entitites import Machine diff --git a/marl_factory_grid/modules/maintenance/groups.py b/marl_factory_grid/modules/maintenance/groups.py index 991071a..045f56f 100644 --- a/marl_factory_grid/modules/maintenance/groups.py +++ b/marl_factory_grid/modules/maintenance/groups.py @@ -2,7 +2,7 @@ from typing import List from .entities import Maintainer from marl_factory_grid.environment.entity.wall_floor import Floor -from marl_factory_grid.environment.groups.env_objects import Collection +from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin from ..machines.actions import MachineAction from ...utils.states import Gamestate From e87bd3aaa0f0d31c56e4b09ac87889266ee287ef Mon Sep 17 00:00:00 2001 From: Chanumask Date: Sun, 22 Oct 2023 12:05:38 +0200 Subject: [PATCH 03/12] all vars are properties, removed comments --- README.md | 2 +- .../environment/entity/entity.py | 5 +- .../environment/entity/object.py | 2 +- marl_factory_grid/environment/entity/wall.py | 31 +++++ .../environment/entity/wall_floor.py | 121 ------------------ .../environment/groups/collection.py | 28 +++- .../environment/groups/global_entities.py | 5 - .../environment/groups/mixins.py | 4 - .../environment/groups/objects.py | 1 - marl_factory_grid/environment/groups/walls.py | 18 +-- .../modules/batteries/constants.py | 2 - .../modules/batteries/entitites.py | 9 +- marl_factory_grid/modules/clean_up/groups.py | 4 - marl_factory_grid/modules/clean_up/rules.py | 2 +- .../modules/destinations/entitites.py | 5 +- .../modules/maintenance/entities.py | 2 - .../modules/maintenance/groups.py | 8 +- marl_factory_grid/modules/zones/entitites.py | 5 - marl_factory_grid/utils/states.py | 5 +- 19 files changed, 66 insertions(+), 193 deletions(-) create mode 100644 marl_factory_grid/environment/entity/wall.py delete mode 100644 marl_factory_grid/environment/entity/wall_floor.py diff --git a/README.md b/README.md index 34208d6..a1d2740 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ General: level_name: rooms # 'double', 'large', 'simple', ... ``` ... or create your own , maybe with the help of [asciiflow.com](https://asciiflow.com/#/). -Make sure to use `#` as [Walls](marl_factory_grid/environment/entity/wall_floor.py), `-` as free (walkable) [Floor](marl_factory_grid/environment/entity/wall_floor.py)-Tiles, `D` for [Walls](./modules/doors/entities.py). +Make sure to use `#` as [Walls](marl_factory_grid/environment/entity/wall.py), `-` as free (walkable) [Floor](marl_factory_grid/environment/entity/wall.py)-Tiles, `D` for [Walls](./modules/doors/entities.py). Other Entites (define you own) may bring their own `Symbols` #### Entites diff --git a/marl_factory_grid/environment/entity/entity.py b/marl_factory_grid/environment/entity/entity.py index eef28a9..900aa6b 100644 --- a/marl_factory_grid/environment/entity/entity.py +++ b/marl_factory_grid/environment/entity/entity.py @@ -5,10 +5,8 @@ import numpy as np from .object import Object from .. import constants as c -from .object import EnvObject -from ...utils.utility_classes import RenderEntity -from ...utils.render import RenderEntity from ...utils.results import ActionResult +from ...utils.utility_classes import RenderEntity class Entity(Object, abc.ABC): @@ -152,7 +150,6 @@ class Entity(Object, abc.ABC): pos = tuple(pos) try: return self.state.entities.pos_dict[pos] - # return next(e for e in self if e.pos == pos) except StopIteration: pass except ValueError: diff --git a/marl_factory_grid/environment/entity/object.py b/marl_factory_grid/environment/entity/object.py index 8596327..6cc61e3 100644 --- a/marl_factory_grid/environment/entity/object.py +++ b/marl_factory_grid/environment/entity/object.py @@ -13,7 +13,7 @@ class Object: return True @property - def var_has_position(self): # brauchen wir das hier jetzt? + def var_has_position(self): try: return self.pos != c.VALUE_NO_POS or False except AttributeError: diff --git a/marl_factory_grid/environment/entity/wall.py b/marl_factory_grid/environment/entity/wall.py new file mode 100644 index 0000000..a10d104 --- /dev/null +++ b/marl_factory_grid/environment/entity/wall.py @@ -0,0 +1,31 @@ +from typing import List + +import numpy as np + +from marl_factory_grid.environment import constants as c +from marl_factory_grid.environment.entity.entity import Entity +from marl_factory_grid.environment.entity.object import EnvObject +from marl_factory_grid.utils.utility_classes import RenderEntity +from marl_factory_grid.utils import helpers as h + + +class Wall(Entity): + + @property + def var_can_collide(self): + return True + + @property + def encoding(self): + return c.VALUE_OCCUPIED_CELL + + def render(self): + return RenderEntity(c.WALL, self.pos) + + @property + def var_is_blocking_pos(self): + return True + + @property + def var_is_blocking_light(self): + return True diff --git a/marl_factory_grid/environment/entity/wall_floor.py b/marl_factory_grid/environment/entity/wall_floor.py deleted file mode 100644 index 9032877..0000000 --- a/marl_factory_grid/environment/entity/wall_floor.py +++ /dev/null @@ -1,121 +0,0 @@ -from typing import List - -import numpy as np - -from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.entity.entity import Entity -from marl_factory_grid.environment.entity.object import EnvObject -from marl_factory_grid.utils.utility_classes import RenderEntity -from marl_factory_grid.utils import helpers as h - - -class Floor(EnvObject): - - @property - def var_has_position(self): - return True - - @property - def var_can_collide(self): - return False - - @property - def var_can_move(self): - return False - - @property - def var_is_blocking_pos(self): - return False - - @property - def var_is_blocking_light(self): - return False - - @property - def encoding(self): - return c.VALUE_OCCUPIED_CELL - - # @property - # def guests_that_can_collide(self): - # return [x for x in self.guests if x.var_can_collide] - - @property - def guests(self): - return self._guests.values() - - @property - def x(self): - return self.pos[0] - - @property - def y(self): - return self.pos[1] - - @property - def is_blocked(self): - return any([x.var_is_blocking_pos for x in self.guests]) - - def __init__(self, pos, **kwargs): - super(Floor, self).__init__(**kwargs) - self._guests = dict() - self.pos = tuple(pos) - self._neighboring_floor: List[Floor] = list() - self._blocked_by = None - - def __len__(self): - return len(self._guests) - - def is_empty(self): - return not len(self._guests) - - def is_occupied(self): - return bool(len(self._guests)) - - def enter(self, guest, spawn=False): - same_pos = guest.name not in self._guests - not_blocked = not self.is_blocked - no_become_blocked_when_occupied = not (guest.var_is_blocking_pos and self.is_occupied()) - not_introduce_collision = not (spawn and guest.var_can_collide and any(x.var_can_collide for x in self.guests)) - if same_pos and not_blocked and no_become_blocked_when_occupied and not_introduce_collision: - self._guests.update({guest.name: guest}) - return c.VALID - else: - return c.NOT_VALID - - def leave(self, guest): - try: - del self._guests[guest.name] - except (ValueError, KeyError): - return c.NOT_VALID - return c.VALID - - def __repr__(self): - return f'{self.name}(@{self.pos})' - - def summarize_state(self, **_): - return dict(name=self.name, x=int(self.x), y=int(self.y)) - - def render(self): - return None - - -class Wall(Entity): - - @property - def var_can_collide(self): - return True - - @property - def encoding(self): - return c.VALUE_OCCUPIED_CELL - - def render(self): - return RenderEntity(c.WALL, self.pos) - - @property - def var_is_blocking_pos(self): - return True - - @property - def var_is_blocking_light(self): - return True diff --git a/marl_factory_grid/environment/groups/collection.py b/marl_factory_grid/environment/groups/collection.py index 65a3b45..8b6f87b 100644 --- a/marl_factory_grid/environment/groups/collection.py +++ b/marl_factory_grid/environment/groups/collection.py @@ -4,13 +4,29 @@ from marl_factory_grid.environment.entity.object import EnvObject class Collection(Objects): _entity = EnvObject - var_is_blocking_light: bool = False - var_can_collide: bool = False - var_can_move: bool = False - var_has_position: bool = False # alles was posmixin hat true - var_has_bound = False # batteries, globalpos, inventories true - var_can_be_bound: bool = False # == ^ + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_collide(self): + return False + + @property + def var_can_move(self): + return False + + @property + def var_has_position(self): + return False # alles was posmixin hat true + @property + def var_has_bound(self): + return False # batteries, globalpos, inventories true + + @property # beide bounds hier? inventory can be bound + def var_can_be_bound(self): + return False @property def encodings(self): diff --git a/marl_factory_grid/environment/groups/global_entities.py b/marl_factory_grid/environment/groups/global_entities.py index d403a41..a1469da 100644 --- a/marl_factory_grid/environment/groups/global_entities.py +++ b/marl_factory_grid/environment/groups/global_entities.py @@ -33,9 +33,6 @@ class Entities(Objects): self.pos_dict = defaultdict(list) super().__init__() - # def all_floors(self): - # return[key for key, val in self.pos_dict.items() if any('floor' in x.name.lower() for x in val)] - def guests_that_can_collide(self, pos): return[x for val in self.pos_dict[pos] for x in val if x.var_can_collide] @@ -91,8 +88,6 @@ class Entities(Objects): def by_pos(self, pos: (int, int)): return self.pos_dict[pos] - # found_entities = [y for y in (x.by_pos(pos) for x in self.values() if hasattr(x, 'by_pos')) if y is not None] - # return found_entities @property def positions(self): diff --git a/marl_factory_grid/environment/groups/mixins.py b/marl_factory_grid/environment/groups/mixins.py index 1a0e885..8a97283 100644 --- a/marl_factory_grid/environment/groups/mixins.py +++ b/marl_factory_grid/environment/groups/mixins.py @@ -1,10 +1,7 @@ from typing import List, Tuple -import numpy as np - from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.entity.entity import Entity -from marl_factory_grid.environment.entity.wall_floor import Floor class PositionMixin: @@ -39,7 +36,6 @@ class PositionMixin: pos = tuple(pos) try: return self.pos_dict[pos] - # return next(e for e in self if e.pos == pos) except StopIteration: pass except ValueError: diff --git a/marl_factory_grid/environment/groups/objects.py b/marl_factory_grid/environment/groups/objects.py index 0e3a49e..c205212 100644 --- a/marl_factory_grid/environment/groups/objects.py +++ b/marl_factory_grid/environment/groups/objects.py @@ -54,7 +54,6 @@ class Objects: assert self._data[item.name] is None, f'{item.name} allready exists!!!' self._data.update({item.name: item}) item.set_collection(self) - # self.notify_add_entity(item) for observer in self.observers: observer.notify_add_entity(item) return self diff --git a/marl_factory_grid/environment/groups/walls.py b/marl_factory_grid/environment/groups/walls.py index 6e42c3f..c02b803 100644 --- a/marl_factory_grid/environment/groups/walls.py +++ b/marl_factory_grid/environment/groups/walls.py @@ -1,10 +1,7 @@ -import random -from typing import List, Tuple - from marl_factory_grid.environment import constants as c +from marl_factory_grid.environment.entity.wall import Wall from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin -from marl_factory_grid.environment.entity.wall_floor import Wall, Floor class Walls(PositionMixin, Collection): @@ -28,16 +25,3 @@ class Walls(PositionMixin, Collection): return super().by_pos(pos)[0] except IndexError: return None - - -class Floors(Walls): - _entity = Floor - symbol = c.SYMBOL_FLOOR - var_is_blocking_light: bool = False - var_can_collide: bool = False - - def __init__(self, *args, **kwargs): - super(Floors, self).__init__(*args, **kwargs) - self._value = c.VALUE_FREE_CELL - - diff --git a/marl_factory_grid/modules/batteries/constants.py b/marl_factory_grid/modules/batteries/constants.py index 77bd920..0f88a08 100644 --- a/marl_factory_grid/modules/batteries/constants.py +++ b/marl_factory_grid/modules/batteries/constants.py @@ -1,5 +1,3 @@ -from typing import NamedTuple, Union - # Battery Env CHARGE_PODS = 'ChargePods' BATTERIES = 'Batteries' diff --git a/marl_factory_grid/modules/batteries/entitites.py b/marl_factory_grid/modules/batteries/entitites.py index f309757..b1aee1e 100644 --- a/marl_factory_grid/modules/batteries/entitites.py +++ b/marl_factory_grid/modules/batteries/entitites.py @@ -1,10 +1,8 @@ -from marl_factory_grid.environment.entity.mixin import BoundEntityMixin -from marl_factory_grid.environment.entity.object import EnvObject, Object -from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment import constants as c -from marl_factory_grid.utils.utility_classes import RenderEntity - +from marl_factory_grid.environment.entity.entity import Entity +from marl_factory_grid.environment.entity.object import Object from marl_factory_grid.modules.batteries import constants as b +from marl_factory_grid.utils.utility_classes import RenderEntity class Battery(Object): @@ -70,7 +68,6 @@ class Pod(Entity): def charge_battery(self, battery: Battery): if battery.charge_level == 1.0: return c.NOT_VALID - # if sum(guest for guest in self.tile.guests if 'agent' in guest.name.lower()) > 1: if sum(1 for key, val in self.state.entities.pos_dict[self.pos] for guest in val if 'agent' in guest.name.lower()) > 1: return c.NOT_VALID diff --git a/marl_factory_grid/modules/clean_up/groups.py b/marl_factory_grid/modules/clean_up/groups.py index 37857a2..6e5a8ad 100644 --- a/marl_factory_grid/modules/clean_up/groups.py +++ b/marl_factory_grid/modules/clean_up/groups.py @@ -45,10 +45,6 @@ class DirtPiles(PositionMixin, Collection): def trigger_dirt_spawn(self, state, initial_spawn=False) -> bool: free_for_dirt = [x for x in state.entities.floorlist if len(state.entities.pos_dict[x]) == 1 or ( len(state.entities.pos_dict[x]) == 2 and isinstance(next(y for y in x), DirtPile))] - # free_for_dirt = [x for x in state[c.FLOOR] - # if len(x.guests) == 0 or ( - # len(x.guests) == 1 and - # isinstance(next(y for y in x.guests), DirtPile))] state.rng.shuffle(free_for_dirt) var = self.dirt_spawn_r_var diff --git a/marl_factory_grid/modules/clean_up/rules.py b/marl_factory_grid/modules/clean_up/rules.py index b7637c9..81a2f59 100644 --- a/marl_factory_grid/modules/clean_up/rules.py +++ b/marl_factory_grid/modules/clean_up/rules.py @@ -54,7 +54,7 @@ class DirtSmearOnMove(Rule): if is_move(entity.state.identifier) and entity.state.validity == c.VALID: if old_pos_dirt := state[d.DIRT].by_pos(entity.last_pos): if smeared_dirt := round(old_pos_dirt.amount * self.smear_amount, 2): - if state[d.DIRT].spawn(entity.pos, amount=smeared_dirt): # pos statt tile + if state[d.DIRT].spawn(entity.pos, amount=smeared_dirt): results.append(TickResult(identifier=self.name, entity=entity, reward=0, validity=c.VALID)) return results diff --git a/marl_factory_grid/modules/destinations/entitites.py b/marl_factory_grid/modules/destinations/entitites.py index 8fffae7..7b866b7 100644 --- a/marl_factory_grid/modules/destinations/entitites.py +++ b/marl_factory_grid/modules/destinations/entitites.py @@ -1,11 +1,10 @@ from collections import defaultdict +from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.environment.entity.entity import Entity -from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.entity.mixin import BoundEntityMixin -from marl_factory_grid.utils.utility_classes import RenderEntity from marl_factory_grid.modules.destinations import constants as d +from marl_factory_grid.utils.utility_classes import RenderEntity class Destination(Entity): diff --git a/marl_factory_grid/modules/maintenance/entities.py b/marl_factory_grid/modules/maintenance/entities.py index 3582197..e084b0c 100644 --- a/marl_factory_grid/modules/maintenance/entities.py +++ b/marl_factory_grid/modules/maintenance/entities.py @@ -84,14 +84,12 @@ class Maintainer(Entity): def _door_is_close(self, state): state.print("Found a door that is close.") try: - # return next(y for x in self.tile.neighboring_floor for y in x.guests if do.DOOR in y.name) return next(y for x in state.entities.neighboring_positions(self.state.pos) for y in state.entities.pos_dict[x] if do.DOOR in y.name) except StopIteration: return None def _predict_move(self, state): next_pos = self._path[0] - # if len(state[c.FLOORS].by_pos(next_pos).guests_that_can_collide) > 0: if any(x for x in state.entities.pos_dict[next_pos] if x.var_can_collide) > 0: action = c.NOOP else: diff --git a/marl_factory_grid/modules/maintenance/groups.py b/marl_factory_grid/modules/maintenance/groups.py index 045f56f..585c34e 100644 --- a/marl_factory_grid/modules/maintenance/groups.py +++ b/marl_factory_grid/modules/maintenance/groups.py @@ -1,14 +1,10 @@ -from typing import List - -from .entities import Maintainer -from marl_factory_grid.environment.entity.wall_floor import Floor from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin +from .entities import Maintainer +from ..machines import constants as mc from ..machines.actions import MachineAction from ...utils.states import Gamestate -from ..machines import constants as mc - class Maintainers(PositionMixin, Collection): diff --git a/marl_factory_grid/modules/zones/entitites.py b/marl_factory_grid/modules/zones/entitites.py index f4923b7..4aa0f70 100644 --- a/marl_factory_grid/modules/zones/entitites.py +++ b/marl_factory_grid/modules/zones/entitites.py @@ -1,12 +1,7 @@ import random from typing import List, Tuple -from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment.entity.object import Object -from marl_factory_grid.utils.utility_classes import RenderEntity -from marl_factory_grid.environment import constants as c - -from marl_factory_grid.modules.doors import constants as d class Zone(Object): diff --git a/marl_factory_grid/utils/states.py b/marl_factory_grid/utils/states.py index 83dbcf9..b234cf3 100644 --- a/marl_factory_grid/utils/states.py +++ b/marl_factory_grid/utils/states.py @@ -57,7 +57,7 @@ class Gamestate(object): @property def moving_entites(self): - return [y for x in self.entities for y in x if x.var_can_move] # wird das aus dem String gelesen? + return [y for x in self.entities for y in x if x.var_can_move] def __init__(self, entities, agents_conf, rules: Dict[str, dict], env_seed=69, verbose=False): self.entities = entities @@ -110,15 +110,12 @@ class Gamestate(object): results.extend(on_check_done_result) return results - def get_all_pos_with_collisions(self) -> List[Tuple[(int, int)]]: positions = [pos for pos, entity_list_for_position in self.entities.pos_dict.items() if any([e.var_can_collide for e in entity_list_for_position])] return positions def check_move_validity(self, moving_entity, position): - # if (guest.name not in self._guests and not self.is_blocked) - # and not (guest.var_is_blocking_pos and self.is_occupied()): if moving_entity.pos != position and not any( entity.var_is_blocking_pos for entity in self.entities.pos_dict[position]) and not ( moving_entity.var_is_blocking_pos and self.entities.is_occupied(position)): From c4ffdb4e446b33b818eb2ffe1b0f4c4304f12d17 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Mon, 23 Oct 2023 16:44:03 +0200 Subject: [PATCH 04/12] object and objects are now private --- marl_factory_grid/environment/entity/entity.py | 4 ++-- marl_factory_grid/environment/entity/object.py | 8 ++++---- marl_factory_grid/environment/entity/util.py | 6 +++--- marl_factory_grid/environment/groups/collection.py | 4 ++-- .../environment/groups/global_entities.py | 6 +++--- marl_factory_grid/environment/groups/objects.py | 14 +++++++------- marl_factory_grid/environment/groups/utils.py | 2 +- marl_factory_grid/modules/batteries/entitites.py | 4 ++-- marl_factory_grid/modules/items/groups.py | 4 ++-- marl_factory_grid/modules/zones/entitites.py | 4 ++-- marl_factory_grid/modules/zones/groups.py | 4 ++-- 11 files changed, 30 insertions(+), 30 deletions(-) diff --git a/marl_factory_grid/environment/entity/entity.py b/marl_factory_grid/environment/entity/entity.py index 900aa6b..9eec210 100644 --- a/marl_factory_grid/environment/entity/entity.py +++ b/marl_factory_grid/environment/entity/entity.py @@ -3,13 +3,13 @@ from collections import defaultdict import numpy as np -from .object import Object +from .object import _Object from .. import constants as c from ...utils.results import ActionResult from ...utils.utility_classes import RenderEntity -class Entity(Object, abc.ABC): +class Entity(_Object, abc.ABC): """Full Env Entity that lives on the environment Grid. Doors, Items, DirtPile etc...""" _u_idx = defaultdict(lambda: 0) diff --git a/marl_factory_grid/environment/entity/object.py b/marl_factory_grid/environment/entity/object.py index 6cc61e3..8312e29 100644 --- a/marl_factory_grid/environment/entity/object.py +++ b/marl_factory_grid/environment/entity/object.py @@ -4,7 +4,7 @@ from typing import Union from marl_factory_grid.environment import constants as c -class Object: +class _Object: """Generell Objects for Organisation and Maintanance such as Actions etc...""" _u_idx = defaultdict(lambda: 0) @@ -66,8 +66,8 @@ class Object: return hash(self.identifier) def _identify_and_count_up(self): - idx = Object._u_idx[self.__class__.__name__] - Object._u_idx[self.__class__.__name__] += 1 + idx = _Object._u_idx[self.__class__.__name__] + _Object._u_idx[self.__class__.__name__] += 1 return idx def set_collection(self, collection): @@ -92,7 +92,7 @@ class Object: return self._bound_entity == entity -class EnvObject(Object): +class EnvObject(_Object): """Objects that hold Information that are observable, but have no position on the environment grid. Inventories etc...""" _u_idx = defaultdict(lambda: 0) diff --git a/marl_factory_grid/environment/entity/util.py b/marl_factory_grid/environment/entity/util.py index bf3866e..945ec87 100644 --- a/marl_factory_grid/environment/entity/util.py +++ b/marl_factory_grid/environment/entity/util.py @@ -3,7 +3,7 @@ import math import numpy as np from marl_factory_grid.environment.entity.mixin import BoundEntityMixin -from marl_factory_grid.environment.entity.object import Object, EnvObject +from marl_factory_grid.environment.entity.object import _Object, EnvObject ########################################################################## @@ -11,7 +11,7 @@ from marl_factory_grid.environment.entity.object import Object, EnvObject ########################################################################## -class PlaceHolder(Object): +class PlaceHolder(_Object): def __init__(self, *args, fill_value=0, **kwargs): super().__init__(*args, **kwargs) @@ -30,7 +30,7 @@ class PlaceHolder(Object): return "PlaceHolder" -class GlobalPosition(Object): +class GlobalPosition(_Object): @property def encoding(self): diff --git a/marl_factory_grid/environment/groups/collection.py b/marl_factory_grid/environment/groups/collection.py index 8b6f87b..bce71c7 100644 --- a/marl_factory_grid/environment/groups/collection.py +++ b/marl_factory_grid/environment/groups/collection.py @@ -1,8 +1,8 @@ -from marl_factory_grid.environment.groups.objects import Objects +from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.environment.entity.object import EnvObject -class Collection(Objects): +class Collection(_Objects): _entity = EnvObject @property diff --git a/marl_factory_grid/environment/groups/global_entities.py b/marl_factory_grid/environment/groups/global_entities.py index a1469da..9b0555a 100644 --- a/marl_factory_grid/environment/groups/global_entities.py +++ b/marl_factory_grid/environment/groups/global_entities.py @@ -3,12 +3,12 @@ from operator import itemgetter from random import shuffle from typing import Dict -from marl_factory_grid.environment.groups.objects import Objects +from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.utils.helpers import POS_MASK -class Entities(Objects): - _entity = Objects +class Entities(_Objects): + _entity = _Objects @staticmethod def neighboring_positions(pos): diff --git a/marl_factory_grid/environment/groups/objects.py b/marl_factory_grid/environment/groups/objects.py index c205212..bea9521 100644 --- a/marl_factory_grid/environment/groups/objects.py +++ b/marl_factory_grid/environment/groups/objects.py @@ -3,12 +3,12 @@ from typing import List import numpy as np -from marl_factory_grid.environment.entity.object import Object +from marl_factory_grid.environment.entity.object import _Object import marl_factory_grid.environment.constants as c -class Objects: - _entity = Object +class _Objects: + _entity = _Object @property def observers(self): @@ -129,8 +129,8 @@ class Objects: self.add_items([self._entity() for _ in range(n)]) return c.VALID - def despawn(self, items: List[Object]): - items = [items] if isinstance(items, Object) else items + def despawn(self, items: List[_Object]): + items = [items] if isinstance(items, _Object) else items for item in items: del self[item] @@ -145,7 +145,7 @@ class Objects: # except (ValueError, AttributeError): # pass - def notify_del_entity(self, entity: Object): + def notify_del_entity(self, entity: _Object): try: entity.del_observer(self) except AttributeError: @@ -155,7 +155,7 @@ class Objects: except (AttributeError, ValueError, IndexError): pass - def notify_add_entity(self, entity: Object): + def notify_add_entity(self, entity: _Object): try: if self not in entity.observers: entity.add_observer(self) diff --git a/marl_factory_grid/environment/groups/utils.py b/marl_factory_grid/environment/groups/utils.py index 542db1c..1971ff0 100644 --- a/marl_factory_grid/environment/groups/utils.py +++ b/marl_factory_grid/environment/groups/utils.py @@ -5,7 +5,7 @@ import numpy as np from marl_factory_grid.environment.entity.util import GlobalPosition from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin -from marl_factory_grid.environment.groups.objects import Objects +from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.modules.zones import Zone from marl_factory_grid.utils import helpers as h from marl_factory_grid.environment import constants as c diff --git a/marl_factory_grid/modules/batteries/entitites.py b/marl_factory_grid/modules/batteries/entitites.py index b1aee1e..235a94f 100644 --- a/marl_factory_grid/modules/batteries/entitites.py +++ b/marl_factory_grid/modules/batteries/entitites.py @@ -1,11 +1,11 @@ from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.entity.entity import Entity -from marl_factory_grid.environment.entity.object import Object +from marl_factory_grid.environment.entity.object import _Object from marl_factory_grid.modules.batteries import constants as b from marl_factory_grid.utils.utility_classes import RenderEntity -class Battery(Object): +class Battery(_Object): @property def var_can_be_bound(self): diff --git a/marl_factory_grid/modules/items/groups.py b/marl_factory_grid/modules/items/groups.py index 5626459..0fb2495 100644 --- a/marl_factory_grid/modules/items/groups.py +++ b/marl_factory_grid/modules/items/groups.py @@ -4,7 +4,7 @@ from marl_factory_grid.modules.items import constants as i from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.objects import Objects +from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.environment.groups.mixins import PositionMixin, IsBoundMixin, HasBoundMixin from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.modules.items.entitites import Item, DropOffLocation @@ -65,7 +65,7 @@ class Inventory(IsBoundMixin, Collection): self._collection = collection -class Inventories(HasBoundMixin, Objects): +class Inventories(HasBoundMixin, _Objects): _entity = Inventory @property diff --git a/marl_factory_grid/modules/zones/entitites.py b/marl_factory_grid/modules/zones/entitites.py index 4aa0f70..cfd313f 100644 --- a/marl_factory_grid/modules/zones/entitites.py +++ b/marl_factory_grid/modules/zones/entitites.py @@ -1,10 +1,10 @@ import random from typing import List, Tuple -from marl_factory_grid.environment.entity.object import Object +from marl_factory_grid.environment.entity.object import _Object -class Zone(Object): +class Zone(_Object): @property def positions(self): diff --git a/marl_factory_grid/modules/zones/groups.py b/marl_factory_grid/modules/zones/groups.py index e706a29..2f668f6 100644 --- a/marl_factory_grid/modules/zones/groups.py +++ b/marl_factory_grid/modules/zones/groups.py @@ -1,8 +1,8 @@ -from marl_factory_grid.environment.groups.objects import Objects +from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.modules.zones import Zone -class Zones(Objects): +class Zones(_Objects): symbol = None _entity = Zone From 0c1d0f510b16d1e4b609ba499a1ec2a8ee79e87e Mon Sep 17 00:00:00 2001 From: Chanumask Date: Tue, 24 Oct 2023 13:33:35 +0200 Subject: [PATCH 05/12] removed positionmix entirely (now also in collection) --- marl_factory_grid/environment/entity/wall.py | 10 ++-- .../environment/groups/agents.py | 17 +++++-- .../environment/groups/collection.py | 49 +++++++++++++++++- .../environment/groups/mixins.py | 51 ------------------- marl_factory_grid/environment/groups/utils.py | 23 +++++---- marl_factory_grid/environment/groups/walls.py | 7 ++- marl_factory_grid/modules/batteries/groups.py | 21 ++++++-- marl_factory_grid/modules/clean_up/groups.py | 24 ++++++--- .../modules/destinations/groups.py | 21 ++++++-- marl_factory_grid/modules/doors/groups.py | 7 ++- marl_factory_grid/modules/items/groups.py | 22 ++++++-- marl_factory_grid/modules/machines/groups.py | 17 +++++-- .../modules/maintenance/groups.py | 24 ++++++--- 13 files changed, 186 insertions(+), 107 deletions(-) diff --git a/marl_factory_grid/environment/entity/wall.py b/marl_factory_grid/environment/entity/wall.py index a10d104..3f0fb7c 100644 --- a/marl_factory_grid/environment/entity/wall.py +++ b/marl_factory_grid/environment/entity/wall.py @@ -1,16 +1,14 @@ -from typing import List - -import numpy as np - from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.entity.entity import Entity -from marl_factory_grid.environment.entity.object import EnvObject from marl_factory_grid.utils.utility_classes import RenderEntity -from marl_factory_grid.utils import helpers as h class Wall(Entity): + @property + def var_has_position(self): + return True + @property def var_can_collide(self): return True diff --git a/marl_factory_grid/environment/groups/agents.py b/marl_factory_grid/environment/groups/agents.py index 571816e..f4a6ac6 100644 --- a/marl_factory_grid/environment/groups/agents.py +++ b/marl_factory_grid/environment/groups/agents.py @@ -1,12 +1,21 @@ from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin -class Agents(PositionMixin, Collection): +class Agents(Collection): _entity = Agent - is_blocking_light = False - can_move = True + + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_move(self): + return True + + @property + def var_has_position(self): + return True def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/marl_factory_grid/environment/groups/collection.py b/marl_factory_grid/environment/groups/collection.py index bce71c7..405fbfe 100644 --- a/marl_factory_grid/environment/groups/collection.py +++ b/marl_factory_grid/environment/groups/collection.py @@ -1,9 +1,12 @@ +from typing import List, Tuple + +from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.environment.entity.object import EnvObject class Collection(_Objects): - _entity = EnvObject + _entity = EnvObject # entity? object? objects? @property def var_is_blocking_light(self): @@ -20,11 +23,12 @@ class Collection(_Objects): @property def var_has_position(self): return False # alles was posmixin hat true + @property def var_has_bound(self): return False # batteries, globalpos, inventories true - @property # beide bounds hier? inventory can be bound + @property # beide bounds hier? inventory can be bound def var_can_be_bound(self): return False @@ -62,3 +66,44 @@ class Collection(_Objects): return next((idx for idx, x in enumerate(self) if x.belongs_to_entity(entity))) except (StopIteration, AttributeError): return None + + def spawn(self, coords: List[Tuple[(int, int)]]): + self.add_items([self._entity(pos) for pos in coords]) + + def render(self): + return [y for y in [x.render() for x in self] if y is not None] + + @classmethod + def from_coordinates(cls, positions: [(int, int)], *args, entity_kwargs=None, **kwargs, ): + collection = cls(*args, **kwargs) + collection.add_items( + [cls._entity(tuple(pos), **entity_kwargs if entity_kwargs is not None else {}) for pos in positions]) + return collection + + def __delitem__(self, name): + idx, obj = next((i, obj) for i, obj in enumerate(self) if obj.name == name) + try: + for observer in obj.observers: + observer.notify_del_entity(obj) + except AttributeError: + pass + super().__delitem__(name) + + def by_pos(self, pos: (int, int)): + pos = tuple(pos) + try: + return self.pos_dict[pos] + except StopIteration: + pass + except ValueError: + print() + + @property + def positions(self): + return [e.pos for e in self] + + def notify_del_entity(self, entity: Entity): + try: + self.pos_dict[entity.pos].remove(entity) + except (ValueError, AttributeError): + pass diff --git a/marl_factory_grid/environment/groups/mixins.py b/marl_factory_grid/environment/groups/mixins.py index 8a97283..48333ca 100644 --- a/marl_factory_grid/environment/groups/mixins.py +++ b/marl_factory_grid/environment/groups/mixins.py @@ -1,55 +1,4 @@ -from typing import List, Tuple - from marl_factory_grid.environment import constants as c -from marl_factory_grid.environment.entity.entity import Entity - - -class PositionMixin: - _entity = Entity - var_is_blocking_light: bool = True - var_can_collide: bool = True - var_has_position: bool = True - - def spawn(self, coords: List[Tuple[(int, int)]]): - self.add_items([self._entity(pos) for pos in coords]) - - def render(self): - return [y for y in [x.render() for x in self] if y is not None] - - @classmethod - def from_coordinates(cls, positions: [(int, int)], *args, entity_kwargs=None, **kwargs, ): - collection = cls(*args, **kwargs) - collection.add_items( - [cls._entity(tuple(pos), **entity_kwargs if entity_kwargs is not None else {}) for pos in positions]) - return collection - - def __delitem__(self, name): - idx, obj = next((i, obj) for i, obj in enumerate(self) if obj.name == name) - try: - for observer in obj.observers: - observer.notify_del_entity(obj) - except AttributeError: - pass - super().__delitem__(name) - - def by_pos(self, pos: (int, int)): - pos = tuple(pos) - try: - return self.pos_dict[pos] - except StopIteration: - pass - except ValueError: - print() - - @property - def positions(self): - return [e.pos for e in self] - - def notify_del_entity(self, entity: Entity): - try: - self.pos_dict[entity.pos].remove(entity) - except (ValueError, AttributeError): - pass # noinspection PyUnresolvedReferences,PyTypeChecker diff --git a/marl_factory_grid/environment/groups/utils.py b/marl_factory_grid/environment/groups/utils.py index 1971ff0..b47b103 100644 --- a/marl_factory_grid/environment/groups/utils.py +++ b/marl_factory_grid/environment/groups/utils.py @@ -1,17 +1,14 @@ from typing import List, Union -import numpy as np - from marl_factory_grid.environment.entity.util import GlobalPosition from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin -from marl_factory_grid.environment.groups.objects import _Objects -from marl_factory_grid.modules.zones import Zone -from marl_factory_grid.utils import helpers as h -from marl_factory_grid.environment import constants as c -class Combined(PositionMixin, Collection): +class Combined(Collection): + + @property + def var_has_position(self): + return True @property def name(self): @@ -38,8 +35,14 @@ class Combined(PositionMixin, Collection): class GlobalPositions(Collection): _entity = GlobalPosition - is_blocking_light = False, - can_collide = False + + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_collide(self): + return False def __init__(self, *args, **kwargs): super(GlobalPositions, self).__init__(*args, **kwargs) diff --git a/marl_factory_grid/environment/groups/walls.py b/marl_factory_grid/environment/groups/walls.py index c02b803..72ccde1 100644 --- a/marl_factory_grid/environment/groups/walls.py +++ b/marl_factory_grid/environment/groups/walls.py @@ -1,13 +1,16 @@ from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.entity.wall import Wall from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin -class Walls(PositionMixin, Collection): +class Walls(Collection): _entity = Wall symbol = c.SYMBOL_WALL + @property + def var_has_position(self): + return True + def __init__(self, *args, **kwargs): super(Walls, self).__init__(*args, **kwargs) self._value = c.VALUE_OCCUPIED_CELL diff --git a/marl_factory_grid/modules/batteries/groups.py b/marl_factory_grid/modules/batteries/groups.py index 90d1fa9..cc0a09d 100644 --- a/marl_factory_grid/modules/batteries/groups.py +++ b/marl_factory_grid/modules/batteries/groups.py @@ -1,13 +1,26 @@ from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin, HasBoundMixin from marl_factory_grid.modules.batteries.entitites import Pod, Battery class Batteries(Collection): _entity = Battery - is_blocking_light: bool = False - can_collide: bool = False + + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_collide(self): + return False + + @property + def var_can_move(self): + return False + + @property + def var_has_position(self): + return True @property def obs_tag(self): @@ -21,7 +34,7 @@ class Batteries(Collection): self.add_items(batteries) -class ChargePods(PositionMixin, Collection): +class ChargePods(Collection): _entity = Pod diff --git a/marl_factory_grid/modules/clean_up/groups.py b/marl_factory_grid/modules/clean_up/groups.py index 6e5a8ad..510d444 100644 --- a/marl_factory_grid/modules/clean_up/groups.py +++ b/marl_factory_grid/modules/clean_up/groups.py @@ -1,14 +1,26 @@ +from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.clean_up.entitites import DirtPile -from marl_factory_grid.environment import constants as c - -class DirtPiles(PositionMixin, Collection): +class DirtPiles(Collection): _entity = DirtPile - is_blocking_light: bool = False - can_collide: bool = False + + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_collide(self): + return False + + @property + def var_can_move(self): + return False + + @property + def var_has_position(self): + return True @property def amount(self): diff --git a/marl_factory_grid/modules/destinations/groups.py b/marl_factory_grid/modules/destinations/groups.py index 4c6e0b9..5f91bb4 100644 --- a/marl_factory_grid/modules/destinations/groups.py +++ b/marl_factory_grid/modules/destinations/groups.py @@ -1,14 +1,27 @@ from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.destinations.entitites import Destination from marl_factory_grid.environment import constants as c from marl_factory_grid.modules.destinations import constants as d -class Destinations(PositionMixin, Collection): +class Destinations(Collection): _entity = Destination - is_blocking_light: bool = False - can_collide: bool = False + + @property + def var_is_blocking_light(self): + return False + + @property + def var_can_collide(self): + return False + + @property + def var_can_move(self): + return False + + @property + def var_has_position(self): + return True def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/marl_factory_grid/modules/doors/groups.py b/marl_factory_grid/modules/doors/groups.py index 3cd9307..687846e 100644 --- a/marl_factory_grid/modules/doors/groups.py +++ b/marl_factory_grid/modules/doors/groups.py @@ -1,16 +1,19 @@ from typing import Union from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin from marl_factory_grid.modules.doors import constants as d from marl_factory_grid.modules.doors.entitites import Door -class Doors(PositionMixin, Collection): +class Doors(Collection): symbol = d.SYMBOL_DOOR _entity = Door + @property + def var_has_position(self): + return True + def __init__(self, *args, **kwargs): super(Doors, self).__init__(*args, can_collide=True, **kwargs) diff --git a/marl_factory_grid/modules/items/groups.py b/marl_factory_grid/modules/items/groups.py index 0fb2495..997f91b 100644 --- a/marl_factory_grid/modules/items/groups.py +++ b/marl_factory_grid/modules/items/groups.py @@ -5,14 +5,18 @@ from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.objects import _Objects -from marl_factory_grid.environment.groups.mixins import PositionMixin, IsBoundMixin, HasBoundMixin +from marl_factory_grid.environment.groups.mixins import IsBoundMixin, HasBoundMixin from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.modules.items.entitites import Item, DropOffLocation -class Items(PositionMixin, Collection): +class Items(Collection): _entity = Item + @property + def var_has_position(self): + return False + @property def is_blocking_light(self): return False @@ -103,17 +107,25 @@ class Inventories(HasBoundMixin, _Objects): state[i.INVENTORY].spawn(state[c.AGENT]) -class DropOffLocations(PositionMixin, Collection): +class DropOffLocations(Collection): _entity = DropOffLocation @property - def is_blocking_light(self): + def var_is_blocking_light(self): return False @property - def can_collide(self): + def var_can_collide(self): return False + @property + def var_can_move(self): + return False + + @property + def var_has_position(self): + return True + def __init__(self, *args, **kwargs): super(DropOffLocations, self).__init__(*args, **kwargs) diff --git a/marl_factory_grid/modules/machines/groups.py b/marl_factory_grid/modules/machines/groups.py index 7d71617..1c70cc2 100644 --- a/marl_factory_grid/modules/machines/groups.py +++ b/marl_factory_grid/modules/machines/groups.py @@ -1,14 +1,23 @@ from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin from .entitites import Machine -class Machines(PositionMixin, Collection): +class Machines(Collection): _entity = Machine - is_blocking_light: bool = False - can_collide: bool = False + + @property + def var_can_collide(self): + return False + + @property + def var_is_blocking_light(self): + return False + + @property + def var_has_position(self): + return True def __init__(self, *args, **kwargs): super(Machines, self).__init__(*args, **kwargs) diff --git a/marl_factory_grid/modules/maintenance/groups.py b/marl_factory_grid/modules/maintenance/groups.py index 585c34e..e25704f 100644 --- a/marl_factory_grid/modules/maintenance/groups.py +++ b/marl_factory_grid/modules/maintenance/groups.py @@ -1,18 +1,28 @@ from marl_factory_grid.environment.groups.collection import Collection -from marl_factory_grid.environment.groups.mixins import PositionMixin from .entities import Maintainer from ..machines import constants as mc from ..machines.actions import MachineAction from ...utils.states import Gamestate -class Maintainers(PositionMixin, Collection): - +class Maintainers(Collection): _entity = Maintainer - var_can_collide = True - var_can_move = True - var_is_blocking_light = False - var_has_position = True + + @property + def var_can_collide(self): + return True + + @property + def var_can_move(self): + return True + + @property + def var_is_blocking_light(self): + return False + + @property + def var_has_position(self): + return True def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) From b13dff925bba552bf87f1de4e1ae09956fc2650d Mon Sep 17 00:00:00 2001 From: Chanumask Date: Fri, 27 Oct 2023 13:08:01 +0200 Subject: [PATCH 06/12] bugfixes --- marl_factory_grid/configs/default_config.yaml | 15 +- .../environment/entity/entity.py | 6 +- .../environment/entity/object.py | 157 ++++++++++-------- marl_factory_grid/environment/entity/util.py | 5 +- .../environment/groups/collection.py | 18 +- .../environment/groups/global_entities.py | 1 - .../environment/groups/objects.py | 14 +- marl_factory_grid/environment/rules.py | 2 +- marl_factory_grid/modules/batteries/groups.py | 2 +- .../modules/destinations/rules.py | 3 +- marl_factory_grid/modules/items/groups.py | 8 +- marl_factory_grid/modules/zones/groups.py | 6 +- .../utils/observation_builder.py | 3 + 13 files changed, 141 insertions(+), 99 deletions(-) diff --git a/marl_factory_grid/configs/default_config.yaml b/marl_factory_grid/configs/default_config.yaml index 5e7b152..7612b27 100644 --- a/marl_factory_grid/configs/default_config.yaml +++ b/marl_factory_grid/configs/default_config.yaml @@ -5,6 +5,19 @@ Agents: - Noop - ItemAction Observations: + - Combined: + - Other + - Walls + - GlobalPosition + - Battery + - ChargePods + - DirtPiles + - Destinations + - Doors + - Items + - Inventory + - DropOffLocations + - Maintainers Wolfgang: Actions: - Noop @@ -64,8 +77,6 @@ Rules: done_at_collisions: false AssignGlobalPositions: {} DestinationReachAny: {} - DestinationReach: - n_dests: 1 DestinationSpawn: n_dests: 1 spawn_frequency: 5 diff --git a/marl_factory_grid/environment/entity/entity.py b/marl_factory_grid/environment/entity/entity.py index 9eec210..bd54ea7 100644 --- a/marl_factory_grid/environment/entity/entity.py +++ b/marl_factory_grid/environment/entity/entity.py @@ -12,8 +12,6 @@ from ...utils.utility_classes import RenderEntity class Entity(_Object, abc.ABC): """Full Env Entity that lives on the environment Grid. Doors, Items, DirtPile etc...""" - _u_idx = defaultdict(lambda: 0) - @property def state(self): return self._status or ActionResult(entity=self, identifier=c.NOOP, validity=c.VALID, reward=0) @@ -29,7 +27,6 @@ class Entity(_Object, abc.ABC): except AttributeError: return False - @property def var_can_move(self): try: @@ -51,7 +48,6 @@ class Entity(_Object, abc.ABC): except AttributeError: return False - @property def x(self): return self.pos[0] @@ -87,7 +83,7 @@ class Entity(_Object, abc.ABC): if valid := state.check_move_validity(self, next_pos): for observer in self.observers: observer.notify_del_entity(self) - self._view_directory = curr_pos[0]-next_pos[0], curr_pos[1]-next_pos[1] + self._view_directory = curr_pos[0] - next_pos[0], curr_pos[1] - next_pos[1] self._pos = next_pos for observer in self.observers: observer.notify_add_entity(self) diff --git a/marl_factory_grid/environment/entity/object.py b/marl_factory_grid/environment/entity/object.py index 8312e29..da77788 100644 --- a/marl_factory_grid/environment/entity/object.py +++ b/marl_factory_grid/environment/entity/object.py @@ -14,10 +14,7 @@ class _Object: @property def var_has_position(self): - try: - return self.pos != c.VALUE_NO_POS or False - except AttributeError: - return False + return False @property def var_can_be_bound(self): @@ -36,6 +33,17 @@ class _Object: return f'{self.__class__.__name__}[{self._str_ident}]' return f'{self.__class__.__name__}#{self.u_int}' + # @property + # def name(self): + # name = f"{self.__class__.__name__}" + # if self.bound_entity: + # name += f"[{self.bound_entity.name}]" + # if self._str_ident is not None: + # name += f"({self._str_ident})" + # else: + # name += f"(#{self.u_int})" + # return name + @property def identifier(self): if self._str_ident is not None: @@ -48,6 +56,7 @@ class _Object: return True def __init__(self, str_ident: Union[str, None] = None, **kwargs): + self._bound_entity = None self._observers = [] self._str_ident = str_ident self.u_int = self._identify_and_count_up() @@ -91,73 +100,83 @@ class _Object: def belongs_to_entity(self, entity): return self._bound_entity == entity - -class EnvObject(_Object): - """Objects that hold Information that are observable, but have no position on the environment grid. Inventories etc...""" - - _u_idx = defaultdict(lambda: 0) - @property - def obs_tag(self): - try: - return self._collection.name or self.name - except AttributeError: - return self.name + def bound_entity(self): + return self._bound_entity - @property - def var_is_blocking_light(self): - try: - return self._collection.var_is_blocking_light or False - except AttributeError: - return False + def bind_to(self, entity): + self._bound_entity = entity - @property - def var_can_be_bound(self): - try: - return self._collection.var_can_be_bound or False - except AttributeError: - return False + def unbind(self): + self._bound_entity = None - @property - def var_can_move(self): - try: - return self._collection.var_can_move or False - except AttributeError: - return False - @property - def var_is_blocking_pos(self): - try: - return self._collection.var_is_blocking_pos or False - except AttributeError: - return False - - @property - def var_has_position(self): - try: - return self._collection.var_has_position or False - except AttributeError: - return False - - @property - def var_can_collide(self): - try: - return self._collection.var_can_collide or False - except AttributeError: - return False - - @property - def encoding(self): - return c.VALUE_OCCUPIED_CELL - - def __init__(self, **kwargs): - super(EnvObject, self).__init__(**kwargs) - - def change_parent_collection(self, other_collection): - other_collection.add_item(self) - self._collection.delete_env_object(self) - self._collection = other_collection - return self._collection == other_collection - - def summarize_state(self): - return dict(name=str(self.name)) +# class EnvObject(_Object): +# """Objects that hold Information that are observable, but have no position on the environment grid. Inventories etc...""" +# + # _u_idx = defaultdict(lambda: 0) +# +# @property +# def obs_tag(self): +# try: +# return self._collection.name or self.name +# except AttributeError: +# return self.name +# +# @property +# def var_is_blocking_light(self): +# try: +# return self._collection.var_is_blocking_light or False +# except AttributeError: +# return False +# +# @property +# def var_can_be_bound(self): +# try: +# return self._collection.var_can_be_bound or False +# except AttributeError: +# return False +# +# @property +# def var_can_move(self): +# try: +# return self._collection.var_can_move or False +# except AttributeError: +# return False +# +# @property +# def var_is_blocking_pos(self): +# try: +# return self._collection.var_is_blocking_pos or False +# except AttributeError: +# return False +# +# @property +# def var_has_position(self): +# try: +# return self._collection.var_has_position or False +# except AttributeError: +# return False +# +# @property +# def var_can_collide(self): +# try: +# return self._collection.var_can_collide or False +# except AttributeError: +# return False +# +# @property +# def encoding(self): +# return c.VALUE_OCCUPIED_CELL +# +# def __init__(self, **kwargs): +# super(EnvObject, self).__init__(**kwargs) +# +# def change_parent_collection(self, other_collection): +# other_collection.add_item(self) +# self._collection.delete_env_object(self) +# self._collection = other_collection +# return self._collection == other_collection +# +# def summarize_state(self): +# return dict(name=str(self.name)) diff --git a/marl_factory_grid/environment/entity/util.py b/marl_factory_grid/environment/entity/util.py index 945ec87..1a5cbe3 100644 --- a/marl_factory_grid/environment/entity/util.py +++ b/marl_factory_grid/environment/entity/util.py @@ -1,9 +1,6 @@ -import math - import numpy as np -from marl_factory_grid.environment.entity.mixin import BoundEntityMixin -from marl_factory_grid.environment.entity.object import _Object, EnvObject +from marl_factory_grid.environment.entity.object import _Object ########################################################################## diff --git a/marl_factory_grid/environment/groups/collection.py b/marl_factory_grid/environment/groups/collection.py index 405fbfe..ee54c03 100644 --- a/marl_factory_grid/environment/groups/collection.py +++ b/marl_factory_grid/environment/groups/collection.py @@ -2,11 +2,11 @@ from typing import List, Tuple from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment.groups.objects import _Objects -from marl_factory_grid.environment.entity.object import EnvObject +from marl_factory_grid.environment.entity.object import _Object class Collection(_Objects): - _entity = EnvObject # entity? object? objects? + _entity = _Object # entity? @property def var_is_blocking_light(self): @@ -22,13 +22,13 @@ class Collection(_Objects): @property def var_has_position(self): - return False # alles was posmixin hat true + return False + + # @property + # def var_has_bound(self): + # return False # batteries, globalpos, inventories true @property - def var_has_bound(self): - return False # batteries, globalpos, inventories true - - @property # beide bounds hier? inventory can be bound def var_can_be_bound(self): return False @@ -40,12 +40,12 @@ class Collection(_Objects): super(Collection, self).__init__(*args, **kwargs) self.size = size - def add_item(self, item: EnvObject): + def add_item(self, item: Entity): assert self.var_has_position or (len(self) <= self.size) super(Collection, self).add_item(item) return self - def delete_env_object(self, env_object: EnvObject): + def delete_env_object(self, env_object): del self[env_object.name] def delete_env_object_by_name(self, name): diff --git a/marl_factory_grid/environment/groups/global_entities.py b/marl_factory_grid/environment/groups/global_entities.py index 9b0555a..7ab48dd 100644 --- a/marl_factory_grid/environment/groups/global_entities.py +++ b/marl_factory_grid/environment/groups/global_entities.py @@ -36,7 +36,6 @@ class Entities(_Objects): def guests_that_can_collide(self, pos): return[x for val in self.pos_dict[pos] for x in val if x.var_can_collide] - @property def empty_positions(self): empty_positions= [key for key in self.floorlist if self.pos_dict[key]] shuffle(empty_positions) diff --git a/marl_factory_grid/environment/groups/objects.py b/marl_factory_grid/environment/groups/objects.py index bea9521..87c9337 100644 --- a/marl_factory_grid/environment/groups/objects.py +++ b/marl_factory_grid/environment/groups/objects.py @@ -122,7 +122,7 @@ class _Objects: raise TypeError def __repr__(self): - repr_dict = { key: val for key, val in self._data.items() if key not in [c.WALLS]} + repr_dict = {key: val for key, val in self._data.items() if key not in [c.WALLS]} return f'{self.__class__.__name__}[{repr_dict}]' def spawn(self, n: int): @@ -169,3 +169,15 @@ class _Objects: # FIXME PROTOBUFF # return [e.summarize_state() for e in self] return [e.summarize_state() for e in self] + + def by_entity(self, entity): + try: + return next((x for x in self if x.belongs_to_entity(entity))) + except (StopIteration, AttributeError): + return None + + def idx_by_entity(self, entity): + try: + return next((idx for idx, x in enumerate(self) if x.belongs_to_entity(entity))) + except (StopIteration, AttributeError): + return None diff --git a/marl_factory_grid/environment/rules.py b/marl_factory_grid/environment/rules.py index 79d4e27..f9678b0 100644 --- a/marl_factory_grid/environment/rules.py +++ b/marl_factory_grid/environment/rules.py @@ -49,7 +49,7 @@ class SpawnAgents(Rule): agent_conf = state.agents_conf # agents = Agents(lvl_map.size) agents = state[c.AGENT] - empty_positions = state.entities.empty_positions[:len(agent_conf)] + empty_positions = state.entities.empty_positions()[:len(agent_conf)] for agent_name in agent_conf: actions = agent_conf[agent_name]['actions'].copy() observations = agent_conf[agent_name]['observations'].copy() diff --git a/marl_factory_grid/modules/batteries/groups.py b/marl_factory_grid/modules/batteries/groups.py index cc0a09d..ee057aa 100644 --- a/marl_factory_grid/modules/batteries/groups.py +++ b/marl_factory_grid/modules/batteries/groups.py @@ -20,7 +20,7 @@ class Batteries(Collection): @property def var_has_position(self): - return True + return False @property def obs_tag(self): diff --git a/marl_factory_grid/modules/destinations/rules.py b/marl_factory_grid/modules/destinations/rules.py index 8773f2d..b5eb9f2 100644 --- a/marl_factory_grid/modules/destinations/rules.py +++ b/marl_factory_grid/modules/destinations/rules.py @@ -36,7 +36,6 @@ class DestinationReachAll(Rule): results.append(TickResult(self.name, validity=c.VALID, reward=r.DEST_REACHED, entity=agent)) return results - def on_check_done(self, state) -> List[DoneResult]: if all(x.was_reached() for x in state[d.DESTINATION]): return [DoneResult(self.name, validity=c.VALID, reward=r.DEST_REACHED)] @@ -56,7 +55,7 @@ class DestinationReachAny(DestinationReachAll): class DestinationSpawn(Rule): - def __init__(self, n_dests: int = 1, + def __init__(self, n_dests: int = 1, spawn_frequency: int = 5, spawn_mode: str = d.MODE_GROUPED): super(DestinationSpawn, self).__init__() self.n_dests = n_dests diff --git a/marl_factory_grid/modules/items/groups.py b/marl_factory_grid/modules/items/groups.py index 997f91b..707f743 100644 --- a/marl_factory_grid/modules/items/groups.py +++ b/marl_factory_grid/modules/items/groups.py @@ -5,7 +5,7 @@ from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.environment.groups.objects import _Objects -from marl_factory_grid.environment.groups.mixins import IsBoundMixin, HasBoundMixin +from marl_factory_grid.environment.groups.mixins import IsBoundMixin from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.modules.items.entitites import Item, DropOffLocation @@ -45,6 +45,10 @@ class Items(Collection): class Inventory(IsBoundMixin, Collection): _accepted_objects = Item + @property + def var_can_be_bound(self): + return True + @property def obs_tag(self): return self.name @@ -69,7 +73,7 @@ class Inventory(IsBoundMixin, Collection): self._collection = collection -class Inventories(HasBoundMixin, _Objects): +class Inventories(_Objects): _entity = Inventory @property diff --git a/marl_factory_grid/modules/zones/groups.py b/marl_factory_grid/modules/zones/groups.py index 2f668f6..71eb329 100644 --- a/marl_factory_grid/modules/zones/groups.py +++ b/marl_factory_grid/modules/zones/groups.py @@ -3,10 +3,12 @@ from marl_factory_grid.modules.zones import Zone class Zones(_Objects): - symbol = None _entity = Zone - var_can_move = False + + @property + def var_can_move(self): + return False def __init__(self, *args, **kwargs): super(Zones, self).__init__(*args, can_collide=True, **kwargs) diff --git a/marl_factory_grid/utils/observation_builder.py b/marl_factory_grid/utils/observation_builder.py index 1377a92..b9d3eac 100644 --- a/marl_factory_grid/utils/observation_builder.py +++ b/marl_factory_grid/utils/observation_builder.py @@ -103,6 +103,7 @@ class OBSBuilder(object): obs = np.zeros((len(agent_want_obs), self.obs_shape[0], self.obs_shape[1])) for idx, l_name in enumerate(agent_want_obs): + print(l_name) try: obs[idx] = pre_sort_obs[l_name] except KeyError: @@ -141,6 +142,8 @@ class OBSBuilder(object): try: v = e.encoding except AttributeError: + print(e) + print(e.var_has_position) raise AttributeError(f'This env. expects Entity-Clases to report their "encoding"') try: np.put(obs[idx], range(len(v)), v, mode='raise') From dd5737e3ff35834144fb862bbea6c51300536fa7 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Fri, 27 Oct 2023 14:14:38 +0200 Subject: [PATCH 07/12] fixed default_config --- marl_factory_grid/configs/default_config.yaml | 21 +++++++++---------- .../modules/destinations/rules.py | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/marl_factory_grid/configs/default_config.yaml b/marl_factory_grid/configs/default_config.yaml index 7612b27..17210e9 100644 --- a/marl_factory_grid/configs/default_config.yaml +++ b/marl_factory_grid/configs/default_config.yaml @@ -69,24 +69,23 @@ General: verbose: false Rules: - Btry: - initial_charge: 0.8 - per_action_costs: 0.02 BtryDoneAtDischarge: {} Collision: done_at_collisions: false AssignGlobalPositions: {} - DestinationReachAny: {} - DestinationSpawn: + DestinationReachReward: {} + SpawnDestinations: n_dests: 1 - spawn_frequency: 5 spawn_mode: GROUPED - DirtAllCleanDone: {} - DirtRespawnRule: + DoneOnAllDirtCleaned: {} + SpawnDirt: + initial_n: 4 + initial_amount: 0.5 + respawn_n: 2 + respawn_amount: 0.2 spawn_freq: 15 - DirtSmearOnMove: - smear_amount: 0.2 - DoorAutoClose: + EntitiesSmearDirtOnMove: {} + DoDoorAutoClose: close_frequency: 10 ItemRules: max_dropoff_storage_size: 0 diff --git a/marl_factory_grid/modules/destinations/rules.py b/marl_factory_grid/modules/destinations/rules.py index 3133e5f..afb8575 100644 --- a/marl_factory_grid/modules/destinations/rules.py +++ b/marl_factory_grid/modules/destinations/rules.py @@ -13,7 +13,7 @@ from marl_factory_grid.modules.destinations.entitites import Destination class DestinationReachReward(Rule): - def __init__(self, dest_reach_reward=marl_factory_grid.modules.destinations.constants.REWARD_DEST_REACHED): + def __init__(self, dest_reach_reward=d.REWARD_DEST_REACHED): """ This rule introduces the basic functionality, so that targts (Destinations) can be reached and marked as such. Additionally, rewards are reported. @@ -50,7 +50,7 @@ class DestinationReachReward(Rule): class DoneAtDestinationReachAll(DestinationReachReward): - def __init__(self, reward_at_done=marl_factory_grid.modules.destinations.constants.REWARD_DEST_DONE, **kwargs): + def __init__(self, reward_at_done=d.REWARD_DEST_DONE, **kwargs): """ This rule triggers and sets the done flag if ALL Destinations have been reached. From 115a79e93017f95d5c5846eb45d3bf5bbdfe19e5 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Fri, 27 Oct 2023 17:46:13 +0200 Subject: [PATCH 08/12] fix mismatching signatures of spawn --- marl_factory_grid/configs/default_config.yaml | 1 + .../environment/groups/collection.py | 18 +++++++++++++---- .../environment/groups/objects.py | 20 ------------------- marl_factory_grid/environment/groups/walls.py | 8 -------- marl_factory_grid/modules/batteries/groups.py | 10 ++++++++-- marl_factory_grid/modules/batteries/rules.py | 2 +- marl_factory_grid/modules/clean_up/groups.py | 7 +++++-- marl_factory_grid/modules/machines/groups.py | 3 +++ marl_factory_grid/modules/machines/rules.py | 3 +-- .../modules/maintenance/groups.py | 7 +++++-- .../modules/maintenance/rules.py | 1 - 11 files changed, 38 insertions(+), 42 deletions(-) diff --git a/marl_factory_grid/configs/default_config.yaml b/marl_factory_grid/configs/default_config.yaml index 17210e9..61168e9 100644 --- a/marl_factory_grid/configs/default_config.yaml +++ b/marl_factory_grid/configs/default_config.yaml @@ -69,6 +69,7 @@ General: verbose: false Rules: + SpawnAgents: {} BtryDoneAtDischarge: {} Collision: done_at_collisions: false diff --git a/marl_factory_grid/environment/groups/collection.py b/marl_factory_grid/environment/groups/collection.py index ee54c03..b89af24 100644 --- a/marl_factory_grid/environment/groups/collection.py +++ b/marl_factory_grid/environment/groups/collection.py @@ -1,8 +1,9 @@ -from typing import List, Tuple +from typing import List, Tuple, Union from marl_factory_grid.environment.entity.entity import Entity from marl_factory_grid.environment.groups.objects import _Objects from marl_factory_grid.environment.entity.object import _Object +import marl_factory_grid.environment.constants as c class Collection(_Objects): @@ -40,6 +41,18 @@ class Collection(_Objects): super(Collection, self).__init__(*args, **kwargs) self.size = size + def spawn(self, coords_or_quantity: Union[int, List[Tuple[(int, int)]]], *entity_args): # woihn mit den args + if isinstance(coords_or_quantity, int): + self.add_items([self._entity() for _ in range(coords_or_quantity)]) + else: + self.add_items([self._entity(pos) for pos in coords_or_quantity]) + return c.VALID + + def despawn(self, items: List[_Object]): + items = [items] if isinstance(items, _Object) else items + for item in items: + del self[item] + def add_item(self, item: Entity): assert self.var_has_position or (len(self) <= self.size) super(Collection, self).add_item(item) @@ -67,9 +80,6 @@ class Collection(_Objects): except (StopIteration, AttributeError): return None - def spawn(self, coords: List[Tuple[(int, int)]]): - self.add_items([self._entity(pos) for pos in coords]) - def render(self): return [y for y in [x.render() for x in self] if y is not None] diff --git a/marl_factory_grid/environment/groups/objects.py b/marl_factory_grid/environment/groups/objects.py index 87c9337..3f42842 100644 --- a/marl_factory_grid/environment/groups/objects.py +++ b/marl_factory_grid/environment/groups/objects.py @@ -125,26 +125,6 @@ class _Objects: repr_dict = {key: val for key, val in self._data.items() if key not in [c.WALLS]} return f'{self.__class__.__name__}[{repr_dict}]' - def spawn(self, n: int): - self.add_items([self._entity() for _ in range(n)]) - return c.VALID - - def despawn(self, items: List[_Object]): - items = [items] if isinstance(items, _Object) else items - for item in items: - del self[item] - - # def notify_change_pos(self, entity: object): - # try: - # self.pos_dict[entity.last_pos].remove(entity) - # except (ValueError, AttributeError): - # pass - # if entity.var_has_position: - # try: - # self.pos_dict[entity.pos].append(entity) - # except (ValueError, AttributeError): - # pass - def notify_del_entity(self, entity: _Object): try: entity.del_observer(self) diff --git a/marl_factory_grid/environment/groups/walls.py b/marl_factory_grid/environment/groups/walls.py index 72ccde1..2d85362 100644 --- a/marl_factory_grid/environment/groups/walls.py +++ b/marl_factory_grid/environment/groups/walls.py @@ -15,14 +15,6 @@ class Walls(Collection): super(Walls, self).__init__(*args, **kwargs) self._value = c.VALUE_OCCUPIED_CELL - #ToDo: Do we need this? Move to spawn methode? - # @classmethod - # def from_coordinates(cls, argwhere_coordinates, *args, **kwargs): - # tiles = cls(*args, **kwargs) - # # noinspection PyTypeChecker - # tiles.add_items([cls._entity(pos) for pos in argwhere_coordinates]) - # return tiles - def by_pos(self, pos: (int, int)): try: return super().by_pos(pos)[0] diff --git a/marl_factory_grid/modules/batteries/groups.py b/marl_factory_grid/modules/batteries/groups.py index ee057aa..2d41bc8 100644 --- a/marl_factory_grid/modules/batteries/groups.py +++ b/marl_factory_grid/modules/batteries/groups.py @@ -1,9 +1,10 @@ +from typing import Union, List, Tuple + from marl_factory_grid.environment.groups.collection import Collection from marl_factory_grid.modules.batteries.entitites import Pod, Battery class Batteries(Collection): - _entity = Battery @property @@ -33,9 +34,14 @@ class Batteries(Collection): batteries = [self._entity(initial_charge_level, agent) for _, agent in enumerate(agents)] self.add_items(batteries) + # def spawn(self, coords_or_quantity: Union[int, List[Tuple[(int, int)]]], *entity_args): hat keine pos + # agents = entity_args[0] + # initial_charge_level = entity_args[1] + # batteries = [self._entity(initial_charge_level, agent) for _, agent in enumerate(agents)] + # self.add_items(batteries) + class ChargePods(Collection): - _entity = Pod def __init__(self, *args, **kwargs): diff --git a/marl_factory_grid/modules/batteries/rules.py b/marl_factory_grid/modules/batteries/rules.py index 6fea262..2089526 100644 --- a/marl_factory_grid/modules/batteries/rules.py +++ b/marl_factory_grid/modules/batteries/rules.py @@ -49,7 +49,7 @@ class BatteryDecharge(Rule): self.per_action_costs = per_action_costs self.initial_charge = initial_charge - def on_init(self, state, lvl_map): + def on_init(self, state, lvl_map): # on reset? assert len(state[c.AGENT]), "There are no agents, did you already spawn them?" state[b.BATTERIES].spawn(state[c.AGENT], self.initial_charge) diff --git a/marl_factory_grid/modules/clean_up/groups.py b/marl_factory_grid/modules/clean_up/groups.py index 304dcad..e585c19 100644 --- a/marl_factory_grid/modules/clean_up/groups.py +++ b/marl_factory_grid/modules/clean_up/groups.py @@ -1,3 +1,5 @@ +from typing import Union, List, Tuple + from marl_factory_grid.environment import constants as c from marl_factory_grid.utils.results import Result from marl_factory_grid.environment.groups.collection import Collection @@ -36,9 +38,10 @@ class DirtPiles(Collection): self.max_global_amount = max_global_amount self.max_local_amount = max_local_amount - def spawn(self, then_dirty_positions, amount_s) -> Result: + def spawn(self, coords_or_quantity: Union[int, List[Tuple[(int, int)]]], *entity_args): + amount_s = entity_args[0] spawn_counter = 0 - for idx, pos in enumerate(then_dirty_positions): + for idx, pos in enumerate(coords_or_quantity): if not self.amount > self.max_global_amount: amount = amount_s[idx] if isinstance(amount_s, list) else amount_s if dirt := self.by_pos(pos): diff --git a/marl_factory_grid/modules/machines/groups.py b/marl_factory_grid/modules/machines/groups.py index 1c70cc2..5f2d970 100644 --- a/marl_factory_grid/modules/machines/groups.py +++ b/marl_factory_grid/modules/machines/groups.py @@ -1,3 +1,5 @@ +from typing import Union, List, Tuple + from marl_factory_grid.environment.groups.collection import Collection from .entitites import Machine @@ -21,3 +23,4 @@ class Machines(Collection): def __init__(self, *args, **kwargs): super(Machines, self).__init__(*args, **kwargs) + diff --git a/marl_factory_grid/modules/machines/rules.py b/marl_factory_grid/modules/machines/rules.py index 84cd4ba..84e3410 100644 --- a/marl_factory_grid/modules/machines/rules.py +++ b/marl_factory_grid/modules/machines/rules.py @@ -13,8 +13,7 @@ class MachineRule(Rule): self.n_machines = n_machines def on_init(self, state, lvl_map): - # TODO Move to spawn!!! - state[m.MACHINES].add_items(Machine(pos) for pos in state.entities.empty_positions()) + state[m.MACHINES].spawn(state.entities.empty_positions()) def tick_pre_step(self, state) -> List[TickResult]: pass diff --git a/marl_factory_grid/modules/maintenance/groups.py b/marl_factory_grid/modules/maintenance/groups.py index e25704f..2df70cb 100644 --- a/marl_factory_grid/modules/maintenance/groups.py +++ b/marl_factory_grid/modules/maintenance/groups.py @@ -1,3 +1,5 @@ +from typing import Union, List, Tuple + from marl_factory_grid.environment.groups.collection import Collection from .entities import Maintainer from ..machines import constants as mc @@ -27,5 +29,6 @@ class Maintainers(Collection): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - def spawn(self, position, state: Gamestate): - self.add_items([self._entity(state, mc.MACHINES, MachineAction(), pos) for pos in position]) + def spawn(self, coords_or_quantity: Union[int, List[Tuple[(int, int)]]], *entity_args): + state = entity_args[0] + self.add_items([self._entity(state, mc.MACHINES, MachineAction(), pos) for pos in coords_or_quantity]) diff --git a/marl_factory_grid/modules/maintenance/rules.py b/marl_factory_grid/modules/maintenance/rules.py index bf73d67..820183e 100644 --- a/marl_factory_grid/modules/maintenance/rules.py +++ b/marl_factory_grid/modules/maintenance/rules.py @@ -14,7 +14,6 @@ class MaintenanceRule(Rule): self.n_maintainer = n_maintainer def on_init(self, state: Gamestate, lvl_map): - # Move to spawn? : #TODO state[M.MAINTAINERS].spawn(state.entities.empty_positions[:self.n_maintainer], state) pass From fbbf8d6f6e9b0bdc10c93856e8957539f24cf11c Mon Sep 17 00:00:00 2001 From: Steffen Illium Date: Mon, 30 Oct 2023 10:08:40 +0100 Subject: [PATCH 09/12] naming Functions --- marl_factory_grid/environment/entity/object.py | 11 +++++++++-- marl_factory_grid/utils/helpers.py | 12 ++++++++++++ marl_factory_grid/utils/observation_builder.py | 8 ++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/marl_factory_grid/environment/entity/object.py b/marl_factory_grid/environment/entity/object.py index da77788..c1518be 100644 --- a/marl_factory_grid/environment/entity/object.py +++ b/marl_factory_grid/environment/entity/object.py @@ -2,6 +2,7 @@ from collections import defaultdict from typing import Union from marl_factory_grid.environment import constants as c +import marl_factory_grid.utils.helpers as h class _Object: @@ -30,8 +31,14 @@ class _Object: @property def name(self): if self._str_ident is not None: - return f'{self.__class__.__name__}[{self._str_ident}]' - return f'{self.__class__.__name__}#{self.u_int}' + name = f'{self.__class__.__name__}[{self._str_ident}]' + else: + name = f'{self.__class__.__name__}#{self.u_int}' + if self.bound_entity: + name = h.add_bound_name(name, self.bound_entity) + if self.var_has_position: + name = h.add_pos_name(name, self) + return name # @property # def name(self): diff --git a/marl_factory_grid/utils/helpers.py b/marl_factory_grid/utils/helpers.py index 8fd3d3a..ad27d29 100644 --- a/marl_factory_grid/utils/helpers.py +++ b/marl_factory_grid/utils/helpers.py @@ -232,3 +232,15 @@ def locate_and_import_class(class_name, folder_path: Union[str, PurePath] = ''): except AttributeError: continue raise AttributeError(f'Class "{class_name}" was not found in "{folder_path.name}"', list(set(all_found_modules))) + + +def add_bound_name(name_str, bound_e): + return f'{name_str}({bound_e.identifier})' + + +def add_pos_name(name_str, bound_e): + if bound_e.var_has_pos: + return f'{name_str}({bound_e.pos})' + return name_str + + diff --git a/marl_factory_grid/utils/observation_builder.py b/marl_factory_grid/utils/observation_builder.py index b9d3eac..6bc0eae 100644 --- a/marl_factory_grid/utils/observation_builder.py +++ b/marl_factory_grid/utils/observation_builder.py @@ -8,6 +8,7 @@ from numba import njit from marl_factory_grid.environment import constants as c from marl_factory_grid.environment.groups.utils import Combined +import marl_factory_grid.utils.helpers as h from marl_factory_grid.utils.states import Gamestate from marl_factory_grid.utils.utility_classes import Floor @@ -118,13 +119,16 @@ class OBSBuilder(object): e = self.all_obs[l_name] except KeyError: try: - e = self.all_obs[f'{l_name}({agent.name})'] + # Look for bound entity names! + e = self.all_obs[h.add_bound_name(l_name, agent)] except KeyError: try: e = next(x for x in self.all_obs if l_name in x and agent.name in x) except StopIteration: raise KeyError( - f'Check typing! {l_name} could not be found in: {list(dict(self.all_obs).keys())}') + f'Check for spelling errors! \n ' + f'No combination of "{l_name} and {agent.name}" could not be found in:\n ' + f'{list(dict(self.all_obs).keys())}') try: positional = e.var_has_position From 00391d2bec2708030d4e2f13ad0cefab54a97531 Mon Sep 17 00:00:00 2001 From: Steffen Illium Date: Mon, 30 Oct 2023 10:11:34 +0100 Subject: [PATCH 10/12] name not identifier --- marl_factory_grid/utils/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marl_factory_grid/utils/helpers.py b/marl_factory_grid/utils/helpers.py index ad27d29..e2cd1eb 100644 --- a/marl_factory_grid/utils/helpers.py +++ b/marl_factory_grid/utils/helpers.py @@ -235,7 +235,7 @@ def locate_and_import_class(class_name, folder_path: Union[str, PurePath] = ''): def add_bound_name(name_str, bound_e): - return f'{name_str}({bound_e.identifier})' + return f'{name_str}({bound_e.name})' def add_pos_name(name_str, bound_e): From ea6634b1878bc9f9e743792261770e654b085203 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Mon, 30 Oct 2023 15:03:18 +0100 Subject: [PATCH 11/12] added regex search for bound entitiy search --- marl_factory_grid/utils/helpers.py | 2 +- marl_factory_grid/utils/observation_builder.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/marl_factory_grid/utils/helpers.py b/marl_factory_grid/utils/helpers.py index e2cd1eb..e2f3c9a 100644 --- a/marl_factory_grid/utils/helpers.py +++ b/marl_factory_grid/utils/helpers.py @@ -239,7 +239,7 @@ def add_bound_name(name_str, bound_e): def add_pos_name(name_str, bound_e): - if bound_e.var_has_pos: + if bound_e.var_has_position: return f'{name_str}({bound_e.pos})' return name_str diff --git a/marl_factory_grid/utils/observation_builder.py b/marl_factory_grid/utils/observation_builder.py index 6bc0eae..f5aa6ec 100644 --- a/marl_factory_grid/utils/observation_builder.py +++ b/marl_factory_grid/utils/observation_builder.py @@ -1,4 +1,5 @@ import math +import re from collections import defaultdict from itertools import product from typing import Dict, List @@ -120,10 +121,13 @@ class OBSBuilder(object): except KeyError: try: # Look for bound entity names! - e = self.all_obs[h.add_bound_name(l_name, agent)] + pattern = re.compile(f'{re.escape(l_name)}(.*){re.escape(agent.name)}') + print(pattern) + name = next((x for x in self.all_obs if pattern.search(x)), None) + e = self.all_obs[name] except KeyError: try: - e = next(x for x in self.all_obs if l_name in x and agent.name in x) + e = next(v for k in self.all_obs.items() if l_name in k and agent.name in k) except StopIteration: raise KeyError( f'Check for spelling errors! \n ' @@ -146,8 +150,6 @@ class OBSBuilder(object): try: v = e.encoding except AttributeError: - print(e) - print(e.var_has_position) raise AttributeError(f'This env. expects Entity-Clases to report their "encoding"') try: np.put(obs[idx], range(len(v)), v, mode='raise') From 4a8c12a5c382a3bd0a53abe62179ccc89ca3c989 Mon Sep 17 00:00:00 2001 From: Chanumask Date: Thu, 2 Nov 2023 12:02:03 +0100 Subject: [PATCH 12/12] fixed render funciton and obsbuilder --- .../environment/groups/collection.py | 15 +++++++++++--- marl_factory_grid/environment/groups/utils.py | 4 ++++ .../modules/batteries/entitites.py | 3 --- marl_factory_grid/modules/batteries/groups.py | 4 ++++ marl_factory_grid/modules/doors/entitites.py | 2 +- marl_factory_grid/modules/items/groups.py | 2 +- .../utils/observation_builder.py | 20 +++++++++---------- 7 files changed, 31 insertions(+), 19 deletions(-) diff --git a/marl_factory_grid/environment/groups/collection.py b/marl_factory_grid/environment/groups/collection.py index b89af24..640c3b4 100644 --- a/marl_factory_grid/environment/groups/collection.py +++ b/marl_factory_grid/environment/groups/collection.py @@ -41,7 +41,7 @@ class Collection(_Objects): super(Collection, self).__init__(*args, **kwargs) self.size = size - def spawn(self, coords_or_quantity: Union[int, List[Tuple[(int, int)]]], *entity_args): # woihn mit den args + def spawn(self, coords_or_quantity: Union[int, List[Tuple[(int, int)]]], *entity_args): # woihn mit den args if isinstance(coords_or_quantity, int): self.add_items([self._entity() for _ in range(coords_or_quantity)]) else: @@ -66,7 +66,13 @@ class Collection(_Objects): @property def obs_pairs(self): - return [(x.name, x) for x in self] + pair_list = [(self.name, self)] + try: + if self.var_can_be_bound: + pair_list.extend([(a.name, a) for a in self]) + except AttributeError: + pass + return pair_list def by_entity(self, entity): try: @@ -81,7 +87,10 @@ class Collection(_Objects): return None def render(self): - return [y for y in [x.render() for x in self] if y is not None] + if self.var_has_position: + return [y for y in [x.render() for x in self] if y is not None] + else: + return [] @classmethod def from_coordinates(cls, positions: [(int, int)], *args, entity_kwargs=None, **kwargs, ): diff --git a/marl_factory_grid/environment/groups/utils.py b/marl_factory_grid/environment/groups/utils.py index b47b103..5619041 100644 --- a/marl_factory_grid/environment/groups/utils.py +++ b/marl_factory_grid/environment/groups/utils.py @@ -44,5 +44,9 @@ class GlobalPositions(Collection): def var_can_collide(self): return False + @property + def var_can_be_bound(self): + return True + def __init__(self, *args, **kwargs): super(GlobalPositions, self).__init__(*args, **kwargs) diff --git a/marl_factory_grid/modules/batteries/entitites.py b/marl_factory_grid/modules/batteries/entitites.py index 235a94f..b51f2dd 100644 --- a/marl_factory_grid/modules/batteries/entitites.py +++ b/marl_factory_grid/modules/batteries/entitites.py @@ -49,9 +49,6 @@ class Battery(_Object): summary.update(dict(belongs_to=self._bound_entity.name, chargeLevel=self.charge_level)) return summary - def render(self): - return None - class Pod(Entity): diff --git a/marl_factory_grid/modules/batteries/groups.py b/marl_factory_grid/modules/batteries/groups.py index 2d41bc8..8d9e060 100644 --- a/marl_factory_grid/modules/batteries/groups.py +++ b/marl_factory_grid/modules/batteries/groups.py @@ -23,6 +23,10 @@ class Batteries(Collection): def var_has_position(self): return False + @property + def var_can_be_bound(self): + return True + @property def obs_tag(self): return self.__class__.__name__ diff --git a/marl_factory_grid/modules/doors/entitites.py b/marl_factory_grid/modules/doors/entitites.py index 0eea655..669f74e 100644 --- a/marl_factory_grid/modules/doors/entitites.py +++ b/marl_factory_grid/modules/doors/entitites.py @@ -12,7 +12,7 @@ class DoorIndicator(Entity): return d.VALUE_ACCESS_INDICATOR def render(self): - return None + return [] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/marl_factory_grid/modules/items/groups.py b/marl_factory_grid/modules/items/groups.py index ea69571..707f743 100644 --- a/marl_factory_grid/modules/items/groups.py +++ b/marl_factory_grid/modules/items/groups.py @@ -135,7 +135,7 @@ class DropOffLocations(Collection): @staticmethod def trigger_drop_off_location_spawn(state, n_locations): - empty_positions = state.entities.empty_positions[:n_locations] + empty_positions = state.entities.empty_positions()[:n_locations] do_entites = state[i.DROP_OFF] drop_offs = [DropOffLocation(pos) for pos in empty_positions] do_entites.add_items(drop_offs) diff --git a/marl_factory_grid/utils/observation_builder.py b/marl_factory_grid/utils/observation_builder.py index bfe30f1..9fd1d26 100644 --- a/marl_factory_grid/utils/observation_builder.py +++ b/marl_factory_grid/utils/observation_builder.py @@ -15,7 +15,6 @@ from marl_factory_grid.utils.utility_classes import Floor class OBSBuilder(object): - default_obs = [c.WALLS, c.OTHERS] @property @@ -95,20 +94,19 @@ class OBSBuilder(object): agent_want_obs = self.obs_layers[agent.name] # Handle in-grid observations aka visible observations (Things on the map, with pos) - visible_entitites = self.ray_caster[agent.name].visible_entities(state.entities.pos_dict) - pre_sort_obs = defaultdict(lambda: np.zeros(self.obs_shape)) + visible_entities = self.ray_caster[agent.name].visible_entities(state.entities.pos_dict) + pre_sort_obs = defaultdict(lambda: np.zeros(self.obs_shape)) if self.pomdp_r: - for e in set(visible_entitites): + for e in set(visible_entities): self.place_entity_in_observation(pre_sort_obs[e.obs_tag], agent, e) else: - for e in set(visible_entitites): + for e in set(visible_entities): pre_sort_obs[e.obs_tag][e.x, e.y] += e.encoding pre_sort_obs = dict(pre_sort_obs) obs = np.zeros((len(agent_want_obs), self.obs_shape[0], self.obs_shape[1])) for idx, l_name in enumerate(agent_want_obs): - print(l_name) try: obs[idx] = pre_sort_obs[l_name] except KeyError: @@ -125,12 +123,11 @@ class OBSBuilder(object): try: # Look for bound entity names! pattern = re.compile(f'{re.escape(l_name)}(.*){re.escape(agent.name)}') - print(pattern) name = next((x for x in self.all_obs if pattern.search(x)), None) e = self.all_obs[name] except KeyError: try: - e = next(v for k in self.all_obs.items() if l_name in k and agent.name in k) + e = next(v for k, v in self.all_obs.items() if l_name in k and agent.name in k) except StopIteration: raise KeyError( f'Check for spelling errors! \n ' @@ -233,7 +230,7 @@ class RayCaster: return f'{self.__class__.__name__}({self.agent.name})' def build_ray_targets(self): - north = np.array([0, -1])*self.pomdp_r + north = np.array([0, -1]) * self.pomdp_r thetas = [np.deg2rad(deg) for deg in np.linspace(-self.degs // 2, self.degs // 2, self.n_rays)[::-1]] rot_M = [ [[math.cos(theta), -math.sin(theta)], @@ -266,8 +263,9 @@ class RayCaster: diag_hits = all([ self.ray_block_cache( key, - lambda: all(False for e in pos_dict[key] if not e.var_is_blocking_light) and bool(pos_dict[key])) - for key in ((x, y-cy), (x-cx, y)) + lambda: all(False for e in pos_dict[key] if not e.var_is_blocking_light) and bool( + pos_dict[key])) + for key in ((x, y - cy), (x - cx, y)) ]) if (cx != 0 and cy != 0) else False visible += entities_hit if not diag_hits else []