Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abmarl 423 enhance supported agent type #517

Merged
merged 7 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions abmarl/examples/sim/comms_blocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,15 @@ def __init__(self, broadcast_mapping=None, **kwargs):
super().__init__(**kwargs)
self.broadcast_mapping = broadcast_mapping
for agent in self.agents.values():
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
agent.action_space[self.key] = Discrete(2)

@property
def key(self):
return 'broadcast'

@property
def supported_agent_type(self):
return BroadcastingAgent
def _supported_agent(self, agent):
return isinstance(agent, BroadcastingAgent)

@property
def broadcast_mapping(self):
Expand Down Expand Up @@ -138,7 +137,7 @@ def determine_broadcast(agent):
receiving_agents.append(other)
return receiving_agents

if isinstance(broadcasting_agent, self.supported_agent_type):
if self._supported_agent(broadcasting_agent):
action = action_dict[self.key]
if action: # Agent has chosen to attack
return determine_broadcast(broadcasting_agent)
Expand Down Expand Up @@ -182,23 +181,22 @@ def __init__(self, broadcasting_state=None, **kwargs):
self._broadcasting_state = broadcasting_state

for agent in self.agents.values():
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
agent.observation_space[self.key] = Dict({
other.id: Box(-1, 1, (1,))
for other in self.agents.values()
if isinstance(other, self.supported_agent_type)
if self._supported_agent(other)
})

@property
def key(self):
return 'message'

@property
def supported_agent_type(self):
return BroadcastingAgent
def _supported_agent(self, agent):
return isinstance(agent, BroadcastingAgent)

def get_obs(self, agent, **kwargs):
if not isinstance(agent, self.supported_agent_type):
if not self._supported_agent(agent):
return {}

obs = {other: 0 for other in agent.observation_space[self.key]}
Expand Down
48 changes: 27 additions & 21 deletions abmarl/sim/gridworld/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ def key(self):
"""
pass

@property
@abstractmethod
def supported_agent_type(self):
def _supported_agent(self, agent):
"""
The type of Agent that this Actor works with.
The qualifications that the agent must satisfy in order to work with this Actor.

For example, Attack Actors require the agent to be an Attacking Agent.

If an agent is this type, the Actor will add its entry to the
agent's action space and will process actions for this agent.
Args:
agent: The agent to inspect.
Returns:
True if agent satisfies qualities, otherwise False.
"""
pass

Expand All @@ -61,7 +64,7 @@ class MoveActor(ActorBaseComponent):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for agent in self.agents.values():
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
if agent.move_range == "FULL":
agent.move_range = max(self.rows, self.cols) - 1
agent.action_space[self.key] = Box(
Expand All @@ -76,12 +79,11 @@ def key(self):
"""
return "move"

@property
def supported_agent_type(self):
def _supported_agent(self, agent):
"""
This Actor works with MovingAgents.
"""
return MovingAgent
return isinstance(agent, MovingAgent)

def process_action(self, agent, action_dict, **kwargs):
"""
Expand All @@ -99,7 +101,7 @@ def process_action(self, agent, action_dict, **kwargs):
Returns:
True if the move is successful, False otherwise.
"""
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
action = action_dict[self.key]
new_position = agent.position + action
if 0 <= new_position[0] < self.rows and \
Expand All @@ -125,7 +127,7 @@ class CrossMoveActor(ActorBaseComponent):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for agent in self.agents.values():
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
agent.action_space[self.key] = Discrete(5)
agent.null_action[self.key] = 0

Expand All @@ -136,12 +138,11 @@ def key(self):
"""
return "move"

@property
def supported_agent_type(self):
def _supported_agent(self, agent):
"""
This Actor works with MovingAgent, but the move_range parameter is ignored.
"""
return MovingAgent
return isinstance(agent, MovingAgent)

def grid_action(self, cross_action):
"""
Expand Down Expand Up @@ -178,7 +179,7 @@ def process_action(self, agent, action_dict, **kwargs):
Returns:
True if the move is successful, False otherwise.
"""
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
cross_action = action_dict[self.key]
action = self.grid_action(cross_action)
new_position = agent.position + action
Expand Down Expand Up @@ -210,6 +211,12 @@ class DriftMoveActor(CrossMoveActor):
that change will fail and it will keep its current orientation, even though
it is blocked that way too.
"""
def _supported_agent(self, agent):
"""
This Actor works with MovingAgent and OrientationAgent.
"""
return isinstance(agent, MovingAgent) and isinstance(agent, OrientationAgent)

def process_action(self, agent, action_dict, **kwargs):
"""
The agent can move up, down, left, right, or stay in place.
Expand All @@ -226,7 +233,7 @@ def process_action(self, agent, action_dict, **kwargs):
Returns:
True if the move is successful, False otherwise.
"""
if isinstance(agent, OrientationAgent) and isinstance(agent, MovingAgent):
if self._supported_agent(agent):
cross_action = action_dict[self.key]
if cross_action != 0:
# Agent has attempted to change directions, let the super process
Expand All @@ -252,7 +259,7 @@ def __init__(self, attack_mapping=None, stacked_attacks=False, **kwargs):
self.attack_mapping = attack_mapping
self.stacked_attacks = stacked_attacks
for agent in self.agents.values():
if isinstance(agent, self.supported_agent_type):
if self._supported_agent(agent):
if agent.attack_range == "FULL":
agent.attack_range = max(self.rows, self.cols) - 1
self._assign_space(agent)
Expand All @@ -264,12 +271,11 @@ def key(self):
"""
return 'attack'

@property
def supported_agent_type(self):
def _supported_agent(self, agent):
"""
This Actor works with AttackingAgents.
"""
return AttackingAgent
return isinstance(agent, AttackingAgent)

@property
def attack_mapping(self):
Expand Down Expand Up @@ -349,7 +355,7 @@ def process_action(self, attacking_agent, action_dict, **kwargs):
2. An attack failed: True, []
3. An attack was successful: True, [non-empty]
"""
if isinstance(attacking_agent, self.supported_agent_type):
if self._supported_agent(attacking_agent):
action = action_dict[self.key]
attack_status, attacked_agents = self._determine_attack(attacking_agent, action)

Expand Down
18 changes: 0 additions & 18 deletions abmarl/sim/gridworld/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,24 +315,6 @@ def initial_ammo(self, value):
self._initial_ammo = value


class AmmoObservingAgentMeta(type):
"""
AmmoObservingAgentMeta class defines an AmmoObservingAgent as an instance of
AmmoAgent and ObservingAgent. Then, when we check if an agent is an instance
of AmmoObservingAgent, it doesn't have to directly derive from it; it just has
to derive from both AmmoAgent and ObservingAgent.
"""
def __instancecheck__(self, instance):
return isinstance(instance, ObservingAgent) and isinstance(instance, AmmoAgent)


class AmmoObservingAgent(AmmoAgent, ObservingAgent, metaclass=AmmoObservingAgentMeta):
"""
Boilterplate class required to work with the AmmoObserver.
"""
pass


class OrientationAgent(GridWorldAgent):
"""
Agent that has an orientation, either 1: Left, 2: Down, 3: Right, 4: Up.
Expand Down
Loading
Loading