Fick die Türen

This commit is contained in:
steffen-illium
2021-06-16 17:28:49 +02:00
parent e223fa3bfe
commit 02523fc05e
6 changed files with 271 additions and 73 deletions
+148 -25
View File
@@ -1,14 +1,19 @@
from typing import Union, List, NamedTuple
from typing import Union, List, NamedTuple, Tuple
import numpy as np
from environments import helpers as h
IS_CLOSED = 'CLOSED'
IS_OPEN = 'OPEN'
class MovementProperties(NamedTuple):
allow_square_movement: bool = True
allow_diagonal_movement: bool = False
allow_no_op: bool = False
# Preperations for Entities (not used yet)
class Entity:
@@ -25,8 +30,59 @@ class Entity:
self._identifier = identifier
class Door(Entity):
@property
def is_closed(self):
return self._state == IS_CLOSED
@property
def is_open(self):
return self._state == IS_OPEN
@property
def status(self):
return self._state
def __init__(self, *args, closed_on_init=True, **kwargs):
super(Door, self).__init__(*args, **kwargs)
self._state = IS_CLOSED if closed_on_init else IS_OPEN
def use(self):
self._state: str = IS_CLOSED if self._state == IS_OPEN else IS_OPEN
pass
class Agent(Entity):
@property
def direction_of_vision(self):
return self._direction_of_vision
def __init__(self, *args, **kwargs):
super(Agent, self).__init__(*args, **kwargs)
self._direction_of_vision = (None, None)
def move(self, new_pos: Tuple[int, int]):
x_old, y_old = self.pos
self._pos = new_pos
x_new, y_new = new_pos
self._direction_of_vision = (x_old-x_new, y_old-y_new)
return self.pos
class AgentState:
@property
def collisions(self):
return np.argwhere(self.collision_vector != 0).flatten()
@property
def direction_of_view(self):
last_x, last_y = self._last_pos
curr_x, curr_y = self.pos
return last_x-curr_x, last_y-curr_y
def __init__(self, i: int, action: int):
self.i = i
self.action = action
@@ -34,18 +90,43 @@ class AgentState:
self.collision_vector = None
self.action_valid = None
self.pos = None
self.info = {}
@property
def collisions(self):
return np.argwhere(self.collision_vector != 0).flatten()
self._last_pos = (-1, -1)
def update(self, **kwargs): # is this hacky?? o.0
last_pos = self.pos
for key, value in kwargs.items():
if hasattr(self, key):
self.__setattr__(key, value)
else:
raise AttributeError(f'"{key}" cannot be updated, this attr is not a part of {self.__class__.__name__}')
raise AttributeError(f'"{key}" cannot be updated, this attr is not a part of {self.__name__}')
if self.action_valid and last_pos != self.pos:
self._last_pos = last_pos
def reset(self):
self.__init__(self.i, self.action)
class DoorState:
def __init__(self, i: int, pos: Tuple[int, int], closed_on_init=True):
self.i = i
self.pos = pos
self._state = self._state = IS_CLOSED if closed_on_init else IS_OPEN
@property
def is_closed(self):
return self._state == IS_CLOSED
@property
def is_open(self):
return self._state == IS_OPEN
@property
def status(self):
return self._state
def use(self):
self._state: str = IS_CLOSED if self._state == IS_OPEN else IS_OPEN
class Register:
@@ -60,24 +141,31 @@ class Register:
def __len__(self):
return len(self._register)
def __add__(self, other: Union[str, List[str]]):
other = other if isinstance(other, list) else [other]
assert all([isinstance(x, str) for x in other]), f'All item names have to be of type {str}.'
self._register.update({key+len(self._register): value for key, value in enumerate(other)})
def __add__(self, other: str):
assert isinstance(other, str), f'All item names have to be of type {str}'
self._register.update({len(self._register): other})
return self
def register_additional_items(self, other: Union[str, List[str]]):
self_with_additional_items = self + other
return self_with_additional_items
def register_additional_items(self, others: List[str]):
for other in others:
self + other
return self
def keys(self):
return self._register.keys()
def values(self):
return self._register.values()
def items(self):
return self._register.items()
def __getitem__(self, item):
return self._register[item]
try:
return self._register[item]
except KeyError:
print('NO')
raise
def by_name(self, item):
return list(self._register.keys())[list(self._register.values()).index(item)]
@@ -86,6 +174,28 @@ class Register:
return f'{self.__class__.__name__}({self._register})'
class Agents(Register):
def __init__(self, n_agents):
super(Agents, self).__init__()
self.register_additional_items([f'agent#{i}' for i in range(n_agents)])
self._agents = [Agent(x, (-1, -1)) for x in self.keys()]
pass
def __getitem__(self, item):
return self._agents[item]
def get_name(self, item):
return self._register[item]
def by_name(self, item):
return self[super(Agents, self).by_name(item)]
def __add__(self, other):
super(Agents, self).__add__(other)
self._agents.append(Agent(len(self)+1, (-1, -1)))
class Actions(Register):
@property
@@ -96,15 +206,12 @@ class Actions(Register):
self.allow_no_op = movement_properties.allow_no_op
self.allow_diagonal_movement = movement_properties.allow_diagonal_movement
self.allow_square_movement = movement_properties.allow_square_movement
# FIXME: There is a bug in helpers because there actions are ints. and the order matters.
# assert not(self.allow_square_movement is False and self.allow_diagonal_movement is True), \
# "There is a bug in helpers!!!"
super(Actions, self).__init__()
if self.allow_square_movement:
self + ['north', 'east', 'south', 'west']
self.register_additional_items(['north', 'east', 'south', 'west'])
if self.allow_diagonal_movement:
self + ['north_east', 'south_east', 'south_west', 'north_west']
self.register_additional_items(['north_east', 'south_east', 'south_west', 'north_west'])
self._movement_actions = self._register.copy()
if self.allow_no_op:
self + 'no-op'
@@ -121,12 +228,19 @@ class Actions(Register):
return self[action] == 'no-op'
class StateSlice(Register):
class StateSlices(Register):
def __init__(self, n_agents: int):
super(StateSlice, self).__init__()
offset = 1 # AGENT_START_IDX
self.register_additional_items(['level', *[f'agent#{i}' for i in range(offset, n_agents+offset)]])
@property
def AGENTSTARTIDX(self):
if self._agent_start_idx:
return self._agent_start_idx
else:
self._agent_start_idx = min([idx for idx, x in self.items() if 'agent' in x])
return self._agent_start_idx
def __init__(self):
super(StateSlices, self).__init__()
self._agent_start_idx = None
class Zones(Register):
@@ -160,3 +274,12 @@ class Zones(Register):
def __getitem__(self, item):
return self._zone_slices[item]
def get_name(self, item):
return self._register[item]
def by_name(self, item):
return self[super(Zones, self).by_name(item)]
def register_additional_items(self, other: Union[str, List[str]]):
raise AttributeError('You are not allowed to add additional Zones in runtime.')