def process(self, map_state: MapState, state: State): super().process(map_state, state) closest_room_id = self.strategy.get_next_room(map_state) # If we've already visited all rooms, then proceed to deliver. if self.strategy.is_all_blocks_found( map_state) or closest_room_id is None: next_state = DeliveringState(self.strategy, self.navigator, self.state_tracker) self.agent.change_state(next_state) return next_state.process(map_state, state) # no current waypoints: find the closest room and go there if len(self.navigator.get_all_waypoints()) == 0: room = map_state.get_room(closest_room_id) door = room['doors'][0]['location'] # if door is closed, reach the spot below it first if not room['doors'][0]['status']: door = door[:1] + (door[1] + 1, ) self.navigator.add_waypoint(door) if self.navigator.is_done: room = map_state.get_room(closest_room_id) self.agent.change_state( ExploringRoomState(self.strategy, self.navigator, self.state_tracker, closest_room_id)) # open the door if it's not open if not room['doors'][0]['status']: return OpenDoorAction.__name__, { 'object_id': room['doors'][0]['door_id'] } return self.navigator.get_move_action(self.state_tracker), {}
def filter_observations(self, state): if self.map_state is None: self.map_state = MapState(state) self.agents = state['World']['team_members'] # Updating the map with visible blocks self.map_state.update_map(None, state) # handle messages for message in self.received_messages: self._handle_message(state, message) # for testing # self.log("current blocks: " + str(self.map_state.blocks)) # self.log("goal blocks:" + str(self.map_state.drop_zone)) # self.log("matching blocks:" + str(self.map_state.get_matching_blocks_within_range(self.map.get_agent_location(state)))) # self.log("self: " + str(self.map_state.get_agent_location(state, None))) # for agent in state.get_agents(): # self.log(str(agent['obj_id']) + ": " + str(self.map_state.get_agent_location(state, agent['obj_id']))) # self.log("wanted colors: " + str(self.map_state._get_goal_colour_set())) # self.log("wanted shape: " + str(self.map_state._get_goal_shape_set())) # self.log("rooms: " + str(self.map_state.rooms)) # self.log("filter: " + str(self.map_state.filter_blocks_within_range(2, self.map_state.get_agent_location(state)))) # self.log("carried blocks: " + str(self.map_state.carried_blocks)) # self.log("agents: " + str(list(map(lambda x: {'block': x['is_carrying'], 'agent': x['obj_id']}, state.get_agents())))) # finally, send all messages stored in the mapstate Queue # SHOULD BE IN DECIDE_ON_BW4T_ACTION BUT HERE FOR DEBUGGING for message in self.map_state.get_message_queue(): self.send_message(message) return state # Why need to returning state
def process(self, map_state: MapState, state: State): super().process(map_state, state) # if we tried to grab a block previous tick, check if we have actually received it from god. if self.pending_goal is not None: res = state.get_with_property({'carried_by': map_state.agent_id}) if res is not None and self.pending_goal['filled']['id'] in [ x['obj_id'] for x in res['is_carrying'] ]: goal_id = self.pending_goal['filled']['id'] self.agent.grab_block([ self.pending_goal['priority'], # priority(order) self.pending_goal['location'], self.pending_goal['filled'], True if goal_id in map_state.carried_blocks.keys() else False ]) map_state.pop_block(goal_id) else: self.remaining.insert(0, self.pending_goal) self.pending_goal = None # pickup all blocks and redeliver them if self.remaining is None: self.remaining = [ goal_block.copy() for goal_block in map_state.goal_blocks if goal_block['filled'] is not None ] self.remaining.sort(key=lambda goal_block: utils.get_distance( map_state.get_agent_location(), goal_block['location'])) for i, goal_block in enumerate(self.remaining): self.remaining[i]['filled'] = map_state.blocks.get( goal_block['filled']) # pickup all blocks while len(self.remaining) > 0: goal_block = self.remaining[0] # if we're too far away, temporarily set new destination to get closer to the block and pick it up # TODO extract hardcoded distance if utils.get_distance(map_state.get_agent_location(), goal_block['location']) > 1: if len(self.navigator.get_all_waypoints() ) == 0 or self.navigator.is_done: self.navigator.reset_full() self.navigator.add_waypoint(goal_block['location']) return self.navigator.get_move_action(self.state_tracker), {} # otherwise grab this block self.pending_goal = goal_block self.remaining.remove(goal_block) return GrabObject.__name__, { 'object_id': goal_block['filled']['id'] } next_state = DeliveringState(self.strategy, self.navigator, self.state_tracker) self.agent.change_state(next_state) return next_state.process(map_state, state)
class Human(HumanAgentBrain): ''' Human that can also handle slowdown. Currently not really implemented, we take the parameter but ignore it. ''' def __init__(self, slowdown: int): super().__init__() self.map_state = None self.agents = None def filter_observations(self, state): if self.map_state is None: self.map_state = MapState(state) self.agents = state['World']['team_members'] # Updating the map with visible blocks self.map_state.update_map(None, state) # handle messages for message in self.received_messages: self._handle_message(state, message) # for testing # self.log("current blocks: " + str(self.map_state.blocks)) # self.log("goal blocks:" + str(self.map_state.drop_zone)) # self.log("matching blocks:" + str(self.map_state.get_matching_blocks_within_range(self.map.get_agent_location(state)))) # self.log("self: " + str(self.map_state.get_agent_location(state, None))) # for agent in state.get_agents(): # self.log(str(agent['obj_id']) + ": " + str(self.map_state.get_agent_location(state, agent['obj_id']))) # self.log("wanted colors: " + str(self.map_state._get_goal_colour_set())) # self.log("wanted shape: " + str(self.map_state._get_goal_shape_set())) # self.log("rooms: " + str(self.map_state.rooms)) # self.log("filter: " + str(self.map_state.filter_blocks_within_range(2, self.map_state.get_agent_location(state)))) # self.log("carried blocks: " + str(self.map_state.carried_blocks)) # self.log("agents: " + str(list(map(lambda x: {'block': x['is_carrying'], 'agent': x['obj_id']}, state.get_agents())))) # finally, send all messages stored in the mapstate Queue # SHOULD BE IN DECIDE_ON_BW4T_ACTION BUT HERE FOR DEBUGGING for message in self.map_state.get_message_queue(): self.send_message(message) return state # Why need to returning state def decide_on_bw4t_action(self, state: State): return super().decide_on_bw4t_action(state) def _handle_message(self, state, message): if type(message) is dict: # self.log("handling message " + str(message)) self.map_state.update_map(message, state) def _broadcast(self, message): self.send_message(message) def log(self, message): print(self.agent_id + ":", message)
def process(self, map_state: MapState, state: State): super().process(map_state, state) # if we don't have any more blocks, just wait if not self.agent.is_holding_blocks(): next_state = WaitingState(self.strategy, self.navigator, self.state_tracker) self.agent.change_state(next_state) return next_state.process(map_state, state) # if not started to drop a box if self.delivering_block is None: self.navigator.reset_full() self.delivering_block = self.agent.get_highest_priority_block() self.navigator.add_waypoint(self.delivering_block[1]) # self.agent.change_state(WalkingState(self.strategy, self.navigator, self.state_tracker)) # when we have reached the earliest drop_zone we can deliver elif self.navigator.is_done: # check if it is our turn to place the block next_goal = map_state.get_next_drop_zone() # for testing reordering # if "normal" not in map_state.agent_id and self.delivering_block[2]['id'] not in next_goal['found_blocks']: # return None, {} # check if the next block to deliver is already delivered if next_goal['priority'] > self.delivering_block[0]: # we don't actually drop this block, but we ignore it within the agent self.agent.drop_block(self.delivering_block) self.delivering_block = None return self.process(map_state, state) # if our block is not the next to deliver, wait if self.delivering_block[2]['id'] not in next_goal['found_blocks']: return None, {} self.navigator.reset_full() self.agent.drop_block(self.delivering_block) drop_block = { 'location': self.delivering_block[1], 'block': self.delivering_block[2] } map_state.drop_block(drop_block) self.delivering_block = None return DropObject.__name__, { 'object_id': drop_block['block']['id'] } return self.navigator.get_move_action(self.state_tracker), {}
def filter_bw4t_observations(self, state) -> State: if self.map_state is None: self.map_state = MapState(state) self.agents = state['World']['team_members'] # Updating the map with visible blocks self.map_state.update_map(None, state) # handle messages # self.log("received: " + str(len(self.received_messages)) + " messages") for message in self.received_messages: if message['type'] == 'Hello': continue if message['agent_id'] != self.map_state.agent_id: self._handle_message(message) self.received_messages.clear() # print(self.map_state.blocks) # for testing # self.log(self.agent_id + " current blocks: " + str(self.map_state.blocks)) # self.log("goal blocks:" + str(self.map.drop_zone)) # self.log("matching blocks:" + str(self.map.get_matching_blocks())) return state
def process(self, map_state: MapState, state: State): # TODO maybe do something smart than just standing there... super().process(map_state, state) # for testing, makes the normal agent not want to go to reordering state. # Might need to comment out the super().process(...) as well. # if "normal" in map_state.agent_id: # return None, {} mismatch = map_state.get_mismatched_spots() # if we have more than one mismatched block and if all blocks have been delivered (yet the game hasn't ended) if len(mismatch) > 0 or sum([ 1 for goal_block in map_state.goal_blocks if goal_block['filled'] ]) == 3: next_state = ReorderingState(self.strategy, self.navigator, self.state_tracker) self.agent.change_state(next_state) return next_state.process(map_state, state) return None, {}
def process(self, map_state: MapState, state: State): super().process(map_state, state) # if we tried to grab a block previous tick, check if we have actually received it from god. if self.pending_block is not None: res = state.get_with_property({'carried_by': map_state.agent_id}) if res is not None and self.pending_block[2]['id'] in [ x['obj_id'] for x in res['is_carrying'] ]: self.agent.grab_block(self.pending_block) map_state.pop_block(self.pending_block[2]) self.pending_block = None if self.strategy.is_all_blocks_found(map_state): next_state = DeliveringState(self.strategy, self.navigator, self.state_tracker) self.agent.change_state(next_state) return next_state.process(map_state, state) room = map_state.get_room(self.room_id) # if just started exploring the room, then initialise the unvisited squares and go towards one of those squares if self.unvisited_squares is None: self.unvisited_squares = set(room['indoor_area']) if len(self.navigator.get_all_waypoints()) == 0: self.navigator.add_waypoint(next(iter(self.unvisited_squares))) # check if any of the blocks match the goal blocks matching_blocks = self.strategy.get_matching_blocks_nearby(map_state) # check if the blocks in the room has been visited if so change traverse strategy if map_state.are_nearby_blocks_visited(): map_state.visit_room(self.room_id) nearby_agents = map_state.get_nearby_agent(state) ability = map_state.agent_ability def switch_traverse_order(self): next_state = WalkingState(self.strategy, self.navigator, self.state_tracker) next_state.strategy.switch_traverse_order() self.agent.change_state(next_state) return next_state.process(map_state, state) if len(nearby_agents) == 0: return switch_traverse_order(self) else: num_agents_same_ability = sum( [1 for i in nearby_agents if i['ability'] == ability]) if num_agents_same_ability == 0 and map_state.agent_ability == 3: return switch_traverse_order(self) random.seed(map_state.agent_id, version=2) if num_agents_same_ability != 0 and random.randint( 1, 10) > (10 / num_agents_same_ability): return switch_traverse_order(self) for block in filter(lambda b: not b[3], matching_blocks): # if we're too far away, temporarily set new destination to get closer to the block and pick it up # TODO extract hardcoded distance if utils.get_distance(map_state.get_agent_location(), block[2]['location']) > 1: self.navigator.reset_full() self.navigator.add_waypoint(block[2]['location']) return self.navigator.get_move_action(self.state_tracker), {} # otherwise grab this block self.navigator.is_done = True self.pending_block = block return GrabObject.__name__, {'object_id': block[2]['id']} # # if full capacity, start delivering # # TODO make this smarter by cooperating with other agents # if self.strategy.is_all_blocks_found: # self.agent.change_state(DeliveringState(self.strategy, self.navigator, self.state_tracker)) # return None, {} # update the unvisited squares self.__update_visited_squares(map_state.get_agent_location()) # if we visited all squares in this room, we can go back to walking if len(self.unvisited_squares) == 0: self.navigator.reset_full() map_state.visit_room(self.room_id) next_state = WalkingState(self.strategy, self.navigator, self.state_tracker) self.agent.change_state(next_state) return next_state.process(map_state, state) # if we have already arrived to our destination, choose a new destination from the unvisited squares in the room if self.navigator.is_done: self.navigator.reset_full() self.navigator.add_waypoint(next(iter(self.unvisited_squares))) return self.navigator.get_move_action(self.state_tracker), {}
class Team42Agent(BW4TBrain): ''' This agent should be dumb but reliable ''' def __init__(self, settings: Dict[str, object]): super().__init__(settings) # self._moves = [MoveNorth.__name__, MoveEast.__name__, MoveSouth.__name__, MoveWest.__name__] self.settings = settings self.strategy: Team42Strategy = None self.map_state: MapState = None self.agents = None self._door_range = 1 self.agent_state: agst.Team42AgentState = None self.holding = [] def initialize(self): super().initialize() self.strategy = Team42Strategy.get_brain_strategy(self.settings, self) # self.map_state = None # self.agents = None self._door_range = 1 # self.agent_state: Team42AgentState = None # self.change_state( self.change_state( self.strategy.initial_state(Navigator(self.agent_id, self.action_set), StateTracker(self.agent_id))) # agst.WalkingState(self.strategy, Navigator(self.agent_id, self.action_set), StateTracker(self.agent_id))) # self.holding = [] def change_state(self, newState: agst.Team42AgentState): self.agent_state = newState self.agent_state.set_agent(self) def grab_block(self, block): self.holding.append(block) self.holding.sort(key=lambda b: b[0]) # for testing, makes the normal agent deliver in reverse order # if "normal" in self.agent_id: # self.holding.sort(key=lambda b: b[0], reverse=True) def drop_block(self, block): for i, b in enumerate(self.holding): if b[1] == block[1]: self.holding.pop(i) return def is_holding_blocks(self): return len(self.agent_properties['is_carrying']) > 0 def is_max_capacity(self): return len(self.agent_properties['is_carrying']) > 2 def get_highest_priority_block(self): return self.holding[0] def filter_bw4t_observations(self, state) -> State: if self.map_state is None: self.map_state = MapState(state) self.agents = state['World']['team_members'] # Updating the map with visible blocks self.map_state.update_map(None, state) # handle messages # self.log("received: " + str(len(self.received_messages)) + " messages") for message in self.received_messages: if message['type'] == 'Hello': continue if message['agent_id'] != self.map_state.agent_id: self._handle_message(message) self.received_messages.clear() # print(self.map_state.blocks) # for testing # self.log(self.agent_id + " current blocks: " + str(self.map_state.blocks)) # self.log("goal blocks:" + str(self.map.drop_zone)) # self.log("matching blocks:" + str(self.map.get_matching_blocks())) return state def decide_on_bw4t_action(self, state: State): # self.log("carrying: " + str(self.map_state.carried_blocks)) action = self.agent_state.process(self.map_state, state) # finally, send all messages stored in the mapstate Queue for message in self.map_state.get_message_queue(): # self.log("sending message " + str(message)) self.send_message(message) return action # def _nearbyDoors(self, state: State): # # copy from humanagent # # Get all doors from the perceived objects # objects = list(state.keys()) # doors = [obj for obj in objects if 'is_open' in state[obj]] # doors_in_range = [] # for object_id in doors: # # Select range as just enough to grab that object # dist = int(np.ceil(np.linalg.norm( # np.array(state[object_id]['location']) - np.array( # state[self.agent_id]['location'])))) # if dist <= self._door_range: # doors_in_range.append(object_id) # return doors_in_range def _handle_message(self, message): if type(message) is dict and message['type'] != None: self.map_state.update_map(message, None) def _broadcast(self, type, data): content = { 'agent_id': self.agent_id, 'type': type, 'blocks': data } # global, so also to itself self.send_message(Message(content=content, from_id=self.agent_id, to_id=None)) # def is_json(self, string): # try: # json_object = json.loads(string) # except ValueError as e: # return False # return True def log(self, message): print(self.agent_id + ":", message)
def get_next_room(self, map_state: MapState): return map_state.get_closest_unvisited_room( map_state.get_agent_location(), self.traverse_order)
def get_matching_blocks_nearby(self, map_state: MapState): return map_state.filter_blocks_within_range( loc=map_state.get_agent_location(), blocks=map_state.get_matching_blocks())