fixed names and function, dirtspawn and item spawn

This commit is contained in:
Steffen Illium
2023-10-30 11:11:35 +01:00
parent ac557232a1
commit 374a38971a
16 changed files with 56 additions and 47 deletions

View File

@@ -60,7 +60,7 @@ Just define what your environment needs in a *yaml*-configfile like:
done_at_collisions: !!bool True done_at_collisions: !!bool True
ItemRespawn: ItemRespawn:
spawn_freq: 5 spawn_freq: 5
DoDoorAutoClose: {} DoorAutoClose: {}
Assets: Assets:
- Defaults - Defaults

View File

@@ -1,10 +1,4 @@
Agents: Agents:
Eberhart:
Actions:
- Move8
- Noop
- ItemAction
Observations:
Wolfgang: Wolfgang:
Actions: Actions:
- Noop - Noop
@@ -29,7 +23,9 @@ Agents:
- DropOffLocations - DropOffLocations
- Maintainers - Maintainers
Entities: Entities:
Batteries: {} Batteries:
initial_charge: 0.8
per_action_costs: 0.02
ChargePods: {} ChargePods: {}
Destinations: {} Destinations: {}
DirtPiles: DirtPiles:
@@ -56,25 +52,21 @@ General:
verbose: false verbose: false
Rules: Rules:
Btry: SpawnAgents: {}
initial_charge: 0.8 DoneAtBatteryDischarge: {}
per_action_costs: 0.02
BtryDoneAtDischarge: {}
Collision: Collision:
done_at_collisions: false done_at_collisions: false
AssignGlobalPositions: {} AssignGlobalPositions: {}
DestinationReachAny: {} DoneAtDestinationReachAny: {}
DestinationReach: DestinationReachReward: {}
SpawnDestinations:
n_dests: 1 n_dests: 1
DestinationSpawn:
n_dests: 1
spawn_frequency: 5
spawn_mode: GROUPED spawn_mode: GROUPED
DirtAllCleanDone: {} DoneOnAllDirtCleaned: {}
DirtRespawnRule: SpawnDirt:
spawn_freq: 15 spawn_freq: 15
DirtSmearOnMove: EntitiesSmearDirtOnMove:
smear_amount: 0.2 smear_ratio: 0.2
DoorAutoClose: DoorAutoClose:
close_frequency: 10 close_frequency: 10
ItemRules: ItemRules:

View File

@@ -12,7 +12,7 @@ class BoundEntityMixin:
if self.bound_entity: if self.bound_entity:
return f'{self.__class__.__name__}({self.bound_entity.name})' return f'{self.__class__.__name__}({self.bound_entity.name})'
else: else:
print() pass
def belongs_to_entity(self, entity): def belongs_to_entity(self, entity):
return entity == self.bound_entity return entity == self.bound_entity

View File

@@ -131,6 +131,7 @@ class EnvObject(Object):
return c.VALUE_OCCUPIED_CELL return c.VALUE_OCCUPIED_CELL
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._bound_entity = None
super(EnvObject, self).__init__(**kwargs) super(EnvObject, self).__init__(**kwargs)
def change_parent_collection(self, other_collection): def change_parent_collection(self, other_collection):

View File

@@ -1,6 +1,6 @@
from collections import defaultdict from collections import defaultdict
from operator import itemgetter from operator import itemgetter
from random import shuffle from random import shuffle, random
from typing import Dict from typing import Dict
from marl_factory_grid.environment.groups.objects import Objects from marl_factory_grid.environment.groups.objects import Objects
@@ -26,6 +26,7 @@ class Entities(Objects):
@property @property
def floorlist(self): def floorlist(self):
shuffle(self._floor_positions)
return self._floor_positions return self._floor_positions
def __init__(self, floor_positions): def __init__(self, floor_positions):

View File

@@ -1,4 +1,4 @@
from .actions import BtryCharge from .actions import BtryCharge
from .entitites import Pod, Battery from .entitites import Pod, Battery
from .groups import ChargePods, Batteries from .groups import ChargePods, Batteries
from .rules import BtryDoneAtDischarge, BatteryDecharge from .rules import DoneAtBatteryDischarge, BatteryDecharge

View File

@@ -94,7 +94,7 @@ class BatteryDecharge(Rule):
return results return results
class BtryDoneAtDischarge(BatteryDecharge): class DoneAtBatteryDischarge(BatteryDecharge):
def __init__(self, reward_discharge_done=b.REWARD_DISCHARGE_DONE, mode: str = b.SINGLE, **kwargs): def __init__(self, reward_discharge_done=b.REWARD_DISCHARGE_DONE, mode: str = b.SINGLE, **kwargs):
f""" f"""

View File

@@ -30,6 +30,7 @@ class DirtPiles(PositionMixin, EnvObjects):
if not self.amount > self.max_global_amount: if not self.amount > self.max_global_amount:
amount = amount_s[idx] if isinstance(amount_s, list) else amount_s amount = amount_s[idx] if isinstance(amount_s, list) else amount_s
if dirt := self.by_pos(pos): if dirt := self.by_pos(pos):
dirt = next(dirt.iter())
new_value = dirt.amount + amount new_value = dirt.amount + amount
dirt.set_new_amount(new_value) dirt.set_new_amount(new_value)
else: else:
@@ -42,8 +43,8 @@ class DirtPiles(PositionMixin, EnvObjects):
return Result(identifier=f'{self.name}_spawn', validity=c.VALID, reward=0, value=spawn_counter) return Result(identifier=f'{self.name}_spawn', validity=c.VALID, reward=0, value=spawn_counter)
def trigger_dirt_spawn(self, n, amount, state, n_var=0.2, amount_var=0.2) -> Result: def trigger_dirt_spawn(self, n, amount, state, n_var=0.2, amount_var=0.2) -> Result:
free_for_dirt = [x for x in state.entities.floorlist if len(state.entities.pos_dict[x]) == 1 or ( free_for_dirt = [x for x in state.entities.floorlist if len(state.entities.pos_dict[x]) == 0 or (
len(state.entities.pos_dict[x]) == 2 and isinstance(next(y for y in x), DirtPile))] len(state.entities.pos_dict[x]) >= 1 and isinstance(next(y for y in x), DirtPile))]
# free_for_dirt = [x for x in state[c.FLOOR] # free_for_dirt = [x for x in state[c.FLOOR]
# if len(x.guests) == 0 or ( # if len(x.guests) == 0 or (
# len(x.guests) == 1 and # len(x.guests) == 1 and

View File

@@ -27,7 +27,8 @@ class DoneOnAllDirtCleaned(Rule):
class SpawnDirt(Rule): class SpawnDirt(Rule):
def __init__(self, initial_n: int, initial_amount: float, respawn_n: int, respawn_amount: float, def __init__(self, initial_n: int = 5, initial_amount: float = 1.3,
respawn_n: int = 3, respawn_amount: float = 0.8,
n_var: float = 0.2, amount_var: float = 0.2, spawn_freq: int = 15): n_var: float = 0.2, amount_var: float = 0.2, spawn_freq: int = 15):
""" """
Defines the spawn pattern of intial and additional 'Dirt'-entitites. Defines the spawn pattern of intial and additional 'Dirt'-entitites.

View File

@@ -13,7 +13,7 @@ from marl_factory_grid.modules.destinations.entitites import Destination
class DestinationReachReward(Rule): 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. This rule introduces the basic functionality, so that targts (Destinations) can be reached and marked as such.
Additionally, rewards are reported. Additionally, rewards are reported.
@@ -50,7 +50,7 @@ class DestinationReachReward(Rule):
class DoneAtDestinationReachAll(DestinationReachReward): 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. This rule triggers and sets the done flag if ALL Destinations have been reached.

View File

@@ -1,4 +1,4 @@
from .actions import DoorUse from .actions import DoorUse
from .entitites import Door, DoorIndicator from .entitites import Door, DoorIndicator
from .groups import Doors from .groups import Doors
from .rules import DoDoorAutoClose, IndicateDoorAreaInObservation from .rules import DoorAutoClose, IndicateDoorAreaInObservation

View File

@@ -5,7 +5,7 @@ from . import constants as d
from .entitites import DoorIndicator from .entitites import DoorIndicator
class DoDoorAutoClose(Rule): class DoorAutoClose(Rule):
def __init__(self, close_frequency: int = 10): def __init__(self, close_frequency: int = 10):
""" """

View File

@@ -104,7 +104,7 @@ class DropOffLocations(PositionMixin, EnvObjects):
@staticmethod @staticmethod
def trigger_drop_off_location_spawn(state, n_locations): 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] do_entites = state[i.DROP_OFF]
drop_offs = [DropOffLocation(pos) for pos in empty_positions] drop_offs = [DropOffLocation(pos) for pos in empty_positions]
do_entites.add_items(drop_offs) do_entites.add_items(drop_offs)

View File

@@ -8,6 +8,7 @@ import yaml
from marl_factory_grid.environment.groups.agents import Agents from marl_factory_grid.environment.groups.agents import Agents
from marl_factory_grid.environment.entity.agent import Agent from marl_factory_grid.environment.entity.agent import Agent
from marl_factory_grid.environment.rules import Rule
from marl_factory_grid.utils.helpers import locate_and_import_class from marl_factory_grid.utils.helpers import locate_and_import_class
from marl_factory_grid.environment import constants as c from marl_factory_grid.environment import constants as c
@@ -81,7 +82,15 @@ class FactoryConfigParser(object):
entity_class = locate_and_import_class(entity, folder_path) entity_class = locate_and_import_class(entity, folder_path)
except AttributeError as e3: except AttributeError as e3:
ents = [y for x in [e1.argss[1], e2.argss[1], e3.argss[1]] for y in x] ents = [y for x in [e1.argss[1], e2.argss[1], e3.argss[1]] for y in x]
raise AttributeError(e1.argss[0], e2.argss[0], e3.argss[0], 'Possible Entitys are:', str(ents)) print('### Error ### Error ### Error ### Error ### Error ###')
print()
print(f'Class "{entity}" was not found in "{folder_path.name}"')
print('Possible Entitys are:', str(ents))
print()
print('Goodbye')
print()
exit()
# raise AttributeError(e1.argss[0], e2.argss[0], e3.argss[0], 'Possible Entitys are:', str(ents))
entity_kwargs = self.entities.get(entity, {}) entity_kwargs = self.entities.get(entity, {})
entity_symbol = entity_class.symbol if hasattr(entity_class, 'symbol') else None entity_symbol = entity_class.symbol if hasattr(entity_class, 'symbol') else None
@@ -114,6 +123,7 @@ class FactoryConfigParser(object):
# Observation # Observation
observations = list() observations = list()
assert self.agents[name]['Observations'] is not None, 'Did you specify any Observation?'
if c.DEFAULTS in self.agents[name]['Observations']: if c.DEFAULTS in self.agents[name]['Observations']:
observations.extend(self.default_observations) observations.extend(self.default_observations)
observations.extend(x for x in self.agents[name]['Observations'] if x != c.DEFAULTS) observations.extend(x for x in self.agents[name]['Observations'] if x != c.DEFAULTS)
@@ -141,6 +151,8 @@ class FactoryConfigParser(object):
rule_class = locate_and_import_class(rule, folder_path) rule_class = locate_and_import_class(rule, folder_path)
except AttributeError: except AttributeError:
rule_class = locate_and_import_class(rule, self.custom_modules_path) rule_class = locate_and_import_class(rule, self.custom_modules_path)
# Fixme This check does not work!
# assert isinstance(rule_class, Rule), f'{rule_class.__name__} is no valid "Rule".'
rule_kwargs = self.rules.get(rule, {}) rule_kwargs = self.rules.get(rule, {})
rules_classes.update({rule: {'class': rule_class, 'kwargs': rule_kwargs}}) rules_classes.update({rule: {'class': rule_class, 'kwargs': rule_kwargs}})
return rules_classes return rules_classes

View File

@@ -148,18 +148,19 @@ class OBSBuilder(object):
np.put(obs[idx], 0, v, mode='raise') np.put(obs[idx], 0, v, mode='raise')
except IndexError: except IndexError:
raise ValueError(f'Max(obs.size) for {e.name}: {obs[idx].size}, but was: {len(v)}.') raise ValueError(f'Max(obs.size) for {e.name}: {obs[idx].size}, but was: {len(v)}.')
if self.pomdp_r:
try: try:
light_map = np.zeros(self.obs_shape) light_map = np.zeros(self.obs_shape)
visible_floor = set(self.ray_caster[agent.name].visible_entities(self._floortiles, reset_cache=False)) visible_floor = set(self.ray_caster[agent.name].visible_entities(self._floortiles, reset_cache=False))
if self.pomdp_r: if self.pomdp_r:
coords = [((f.x - agent.x) + self.pomdp_r, (f.y - agent.y) + self.pomdp_r) for f in visible_floor] # Fixme: This Sucks if the Map is too small!!
else: coords = [((f.x - agent.x) + self.pomdp_r, (f.y - agent.y) + self.pomdp_r) for f in visible_floor]
coords = [x.pos for x in visible_floor] else:
np.put(light_map, np.ravel_multi_index(np.asarray(coords).T, light_map.shape), 1) coords = [x.pos for x in visible_floor]
self.curr_lightmaps[agent.name] = light_map np.put(light_map, np.ravel_multi_index(np.asarray(coords).T, light_map.shape), 1)
except KeyError: self.curr_lightmaps[agent.name] = light_map
print() except (KeyError, ValueError):
pass
return obs, self.obs_layers[agent.name] return obs, self.obs_layers[agent.name]
def _sort_and_name_observation_conf(self, agent): def _sort_and_name_observation_conf(self, agent):

View File

@@ -88,8 +88,8 @@ class Gamestate(object):
results.extend(self.rules.tick_pre_step_all(self)) results.extend(self.rules.tick_pre_step_all(self))
for idx, action_int in enumerate(actions): for idx, action_int in enumerate(actions):
agent = self[c.AGENT][idx].clear_temp_state()
if not agent.var_is_paralyzed: if not agent.var_is_paralyzed:
agent = self[c.AGENT][idx].clear_temp_state()
action = agent.actions[action_int] action = agent.actions[action_int]
action_result = action.do(agent, self) action_result = action.do(agent, self)
results.append(action_result) results.append(action_result)