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)
def get_door_order(self): """ Returns the optimal order in which to visit the rooms. Starts with the room closest to our current location and iteratively adds the room closest to the last room. """ objects = list(self.state.keys()) doors = [self.state[obj] for obj in objects if ('door' in obj)] ret = [] current_loc = self.state[self.agent_id]['location'] while len(doors): min_dist = 1e9 door = None for x in doors: dist = get_distance(x['location'], current_loc) if dist < min_dist: door = x min_dist = dist current_loc = door['location'] doors.remove(door) ret.append(door) return ret
def get_grabbable_blocks(self, blocks): """ Return the blocks which the agent is able to pick up, i.e. in the pickup range, and that correspond to a drop zone """ ret = [] for block in blocks: if get_distance(block['location'], self.state[self.agent_id]['location']) <= 1: for drop in self.left_to_find().values(): if self.check_look_same(drop, self.knowledge[block['obj_id']]): ret.append(block) break return ret
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), {}
def decide_on_bw4t_action(self, state: State): # Open any nearby closed doors if self.phase is Phase.EXPLORING: for doorId in self._nearbyDoors(state): if not state[doorId]['is_open']: return OpenDoorAction.__name__, {'object_id': doorId} current_loc = self.state[self.agent_id]['location'] if current_loc in self.tiles: possible_match = [ x for x in self.get_nearby_blocks(self.state) if any([ self.check_partially_look_same(x, y) for y in self.left_to_find().values() ]) ] blocks = set(map(lambda x: x['location'], possible_match)) next_waypoints = list( map(lambda x: x[1], self.navigator.get_upcoming_waypoints())) to_remove = list( x for x in next_waypoints if get_distance(x, current_loc) <= self.block_range and x not in blocks) new_waypoints = [ x for x in next_waypoints if x not in to_remove ] self.navigator.reset_full() self.navigator.add_waypoints(new_waypoints) # Try to grab/drop objects if you are in pickup phase elif self.phase is Phase.PICKUP: return GrabObject.__name__, { 'object_id': random.choice(self.can_grab)['obj_id'] } elif self.phase is Phase.DROP: # Check if the agent is on a drop zone if self.targets and self.state[self.agent_id][ 'location'] == self.state[self.targets[0]]['location']: loc = self.state[self.agent_id]['location'] # Check underneath you possible_match = [ x for x in self.state.values() if ('location' in x and x['location'] == (loc[0], loc[1] + 1)) ] # If there is a wall below or a box is dropped immediately below this tile we can drop our box # possible_match == 1 means wall underneath if len(possible_match) == 1 or (loc[0], loc[1] + 1) in self.dropped or any([ x['is_collectable'] for x in possible_match if 'is_collectable' in x ]): object_id = None # Checks to see if any blocks are placed above current location blocks_above = [ x for x in self.get_nearby_blocks(self.state) if x['location'] == (loc[0], loc[1] - 1) ] if blocks_above: try: # Try and get the drop zone corresponding to the location (if it exists) new_target = \ [x for x in self.drops if self.drops[x]['location'] == blocks_above[0]['location']][0] # Add the above dropzone to the targets list self.targets.insert(1, new_target) # Update the navigator to go through the drop zone above new_waypoints = [ self.drops[new_target]['location'] ] new_waypoints.extend( list( map( lambda x: x[1], self.navigator.get_upcoming_waypoints( )))) self.navigator.reset_full() self.navigator.add_waypoints(new_waypoints) # Grab the object placed above return GrabObject.__name__, { 'object_id': blocks_above[0]['obj_id'] } except: pass # Select drop zone the agent is standing on for drop in self.drop_to_block: if self.state[drop]['location'] == loc: object_id = drop break self.targets.pop(0) blockid_to_drop = self.drop_to_block[object_id] # Send drop message after the drop action has been executed self.current_action_tick_started = state['World'][ 'nr_ticks'] self.message_queue.append( (dropped, (self, self.knowledge[blockid_to_drop], state[self.agent_id]['location']))) return DropObject.__name__, {'object_id': blockid_to_drop} else: # Wait for someone to drop their object before you drop yours return None, {} self.state_tracker.update(state) try: action = self.navigator.get_move_action(self.state_tracker) except: return None, {} return action, {}