예제 #1
0
    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), {}
예제 #2
0
    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
예제 #3
0
    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)
예제 #4
0
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)
예제 #5
0
    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), {}
예제 #6
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
예제 #7
0
    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, {}
예제 #8
0
    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), {}
예제 #9
0
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)
예제 #10
0
 def get_next_room(self, map_state: MapState):
     return map_state.get_closest_unvisited_room(
         map_state.get_agent_location(), self.traverse_order)
예제 #11
0
 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())