# Path: oscar/agent/commander/base_commander.py
# class BaseCommander(ABC, CustomAgent):
#     """
#     A base class for commander agents.
#     These are specialized agents that capable of delegating tasks to subordinates
#     """
# 
#     def __init__(self, subordinates: list):
#         """
#         :param subordinates: a list of agents. These must be initialized already !
#         """
#         super().__init__()
#         self._subordinates = subordinates
#         self._locked_choice = False
#         self._playing_subordinate = None
# 
#     def step(self, obs, locked_choice=None):
#         """
#         Does some work and choose a subordinate that will play
#         :param obs: observations from the game
#         :return: an action chosen by a subordinate
#         """
# 
#         """if not self._locked_choice:
#             self._playing_subordinate = self.choose_subordinate(obs)
#         play = self._playing_subordinate.step(obs)
#         try:
#             self._locked_choice = play["locked_choice"]
#         except KeyError:
#             self._locked_choice = False
#         return play"""
# 
#         if locked_choice is None:
#             locked_choice = self._locked_choice
# 
#         self._playing_subordinate = self.choose_subordinate(obs, locked_choice)
#         play = self._playing_subordinate.step(obs, locked_choice)
#         if "locked_choice" in play:
#             self._locked_choice = play["locked_choice"]
#         else:
#             self._locked_choice = False
#         return play
# 
#     def add_subordinate(self, agent):
#         """
#         Hires a subordinate
#         :param agent: to add
#         :return:
#         """
#         self._subordinates.append(agent)
# 
#     def remove_subordinate(self, agent):
#         """
#         Fires a subordinate
#         :param agent: to remove
#         :return:
#         """
#         self._subordinates.remove(agent)
# 
#     @abstractmethod
#     def choose_subordinate(self, obs, locked_choice):
#         """
#         Choose a subordinate among the list of subordinates, and make it play.
#         :return: A subordinate among the list of subordinates.
#         """
# 
#     def play_locked_choice(self):
#         return self._playing_subordinate
# 
#     def unlock_choice(self):
#         if self._locked_choice:
#             self._locked_choice = False
#             try:
#                 self._playing_subordinate.unlock_choice()
#             # Method does not exist = not a commander
#             except AttributeError:
#                 pass
# 
#     def setup(self, obs_spec, action_spec):
#         super().setup(obs_spec, action_spec)
#         for subordinate in self._subordinates:
#             subordinate.setup(obs_spec, action_spec)
# 
#     def reset(self):
#         super().reset()
#         for subordinate in self._subordinates:
#             subordinate.reset()
# 
#     def __str__(self):
#         """
#         See print_tree
#         :return:
#         """
#         return self.print_tree(0)
# 
#     def print_tree(self, depth):
#         """
#         Recursively builds the hierarchy tree of the agent
#         :param depth: current depth in the general tree (used for indentation in the string)
#         :return: hierarchy tree (string)
#         """
#         depth += 1
#         ret = "I am a {} and I have {} subordinates :\n".format(type(self).__name__, len(self._subordinates))
#         for subordinate in self._subordinates:
#             ret += "\t" * depth
#             try:
#                 ret += subordinate.print_tree(depth + 1)
#             except AttributeError:
#                 ret += str(subordinate) + "\n"
#         return ret
# 
# Path: oscar/util/point.py
# class Point:
# 
#     def __init__(self, x=None, y=None):
#         self.x = x
#         self.y = y
# 
#     def squared_distance(self, other):
#         return (self.x-other.x)*(self.x-other.x) + (self.y-other.y)*(self.y-other.y)
# 
#     def distance(self, other):
#         return math.sqrt(self.squared_distance(other))
# 
#     def get_flipped(self):
#         return Point(self.y, self.x)
# 
#     def to_array(self):
#         return [self.x, self.y]
# 
#     def equals(self, other):
#         return self.x == other.x and self.y == other.y
# 
#     def difference(self, other):
#         return Point(self.x - other.x, self.y - other.y)
# 
#     def addition(self, other):
#         return Point(self.x + other.x, self.y + other.y)
# 
#     def __str__(self):
#         return "Point("+str(self.x)+","+str(self.y)+")"


from abc import ABC, abstractmethod
from oscar.agent.commander.base_commander import BaseCommander
from oscar.util.point import Point
from oscar.meta_action import *
            context = self._subordinate_context[subordinate]
        play = {}
        play['actions'] = [actions.FunctionCall(MOVE_CAMERA, [context.camera.to_array()])]
        play['locked_choice'] = True
        self._is_changing_context = True
        return play

    def save_context(self, obs):
        context = AgentContext()
        location = self._shared['camera'].location(obs=obs, shared=self._shared)
        context.camera = location
        self._subordinate_context[self._playing_subordinate] = context

    @abstractmethod
    def choose_subordinate(self, obs, locked_choice):
        """
        Choose a subordinate among the list of subordinates, and make it play.
        :return: A subordinate among the list of subordinates.
        """

    def reset(self):
        super().reset()
        self._subordinate_context = {}
        self._is_changing_context = False
        self.add_shared('env', Env())
        self.add_shared('camera', Camera())


class AgentContext:
    def __init__(self):

# Path: oscar/agent/commander/base_commander.py
# class BaseCommander(ABC, CustomAgent):
#     """
#     A base class for commander agents.
#     These are specialized agents that capable of delegating tasks to subordinates
#     """
# 
#     def __init__(self, subordinates: list):
#         """
#         :param subordinates: a list of agents. These must be initialized already !
#         """
#         super().__init__()
#         self._subordinates = subordinates
#         self._locked_choice = False
#         self._playing_subordinate = None
# 
#     def step(self, obs, locked_choice=None):
#         """
#         Does some work and choose a subordinate that will play
#         :param obs: observations from the game
#         :return: an action chosen by a subordinate
#         """
# 
#         """if not self._locked_choice:
#             self._playing_subordinate = self.choose_subordinate(obs)
#         play = self._playing_subordinate.step(obs)
#         try:
#             self._locked_choice = play["locked_choice"]
#         except KeyError:
#             self._locked_choice = False
#         return play"""
# 
#         if locked_choice is None:
#             locked_choice = self._locked_choice
# 
#         self._playing_subordinate = self.choose_subordinate(obs, locked_choice)
#         play = self._playing_subordinate.step(obs, locked_choice)
#         if "locked_choice" in play:
#             self._locked_choice = play["locked_choice"]
#         else:
#             self._locked_choice = False
#         return play
# 
#     def add_subordinate(self, agent):
#         """
#         Hires a subordinate
#         :param agent: to add
#         :return:
#         """
#         self._subordinates.append(agent)
# 
#     def remove_subordinate(self, agent):
#         """
#         Fires a subordinate
#         :param agent: to remove
#         :return:
#         """
#         self._subordinates.remove(agent)
# 
#     @abstractmethod
#     def choose_subordinate(self, obs, locked_choice):
#         """
#         Choose a subordinate among the list of subordinates, and make it play.
#         :return: A subordinate among the list of subordinates.
#         """
# 
#     def play_locked_choice(self):
#         return self._playing_subordinate
# 
#     def unlock_choice(self):
#         if self._locked_choice:
#             self._locked_choice = False
#             try:
#                 self._playing_subordinate.unlock_choice()
#             # Method does not exist = not a commander
#             except AttributeError:
#                 pass
# 
#     def setup(self, obs_spec, action_spec):
#         super().setup(obs_spec, action_spec)
#         for subordinate in self._subordinates:
#             subordinate.setup(obs_spec, action_spec)
# 
#     def reset(self):
#         super().reset()
#         for subordinate in self._subordinates:
#             subordinate.reset()
# 
#     def __str__(self):
#         """
#         See print_tree
#         :return:
#         """
#         return self.print_tree(0)
# 
#     def print_tree(self, depth):
#         """
#         Recursively builds the hierarchy tree of the agent
#         :param depth: current depth in the general tree (used for indentation in the string)
#         :return: hierarchy tree (string)
#         """
#         depth += 1
#         ret = "I am a {} and I have {} subordinates :\n".format(type(self).__name__, len(self._subordinates))
#         for subordinate in self._subordinates:
#             ret += "\t" * depth
#             try:
#                 ret += subordinate.print_tree(depth + 1)
#             except AttributeError:
#                 ret += str(subordinate) + "\n"
#         return ret
# 
# Path: oscar/util/point.py
# class Point:
# 
#     def __init__(self, x=None, y=None):
#         self.x = x
#         self.y = y
# 
#     def squared_distance(self, other):
#         return (self.x-other.x)*(self.x-other.x) + (self.y-other.y)*(self.y-other.y)
# 
#     def distance(self, other):
#         return math.sqrt(self.squared_distance(other))
# 
#     def get_flipped(self):
#         return Point(self.y, self.x)
# 
#     def to_array(self):
#         return [self.x, self.y]
# 
#     def equals(self, other):
#         return self.x == other.x and self.y == other.y
# 
#     def difference(self, other):
#         return Point(self.x - other.x, self.y - other.y)
# 
#     def addition(self, other):
#         return Point(self.x + other.x, self.y + other.y)
# 
#     def __str__(self):
#         return "Point("+str(self.x)+","+str(self.y)+")"


# Path: oscar/agent/commander/context_save_commender.py
from abc import ABC, abstractmethod
from oscar.agent.commander.base_commander import BaseCommander
from oscar.util.point import Point
from oscar.meta_action import *

            context = self._subordinate_context[subordinate]
        play = {}
        play['actions'] = [actions.FunctionCall(MOVE_CAMERA, [context.camera.to_array()])]
        play['locked_choice'] = True
        self._is_changing_context = True
        return play

    def save_context(self, obs):
        context = AgentContext()
        location = self._shared['camera'].location(obs=obs, shared=self._shared)
        context.camera = location
        self._subordinate_context[self._playing_subordinate] = context

    @abstractmethod
    def choose_subordinate(self, obs, locked_choice):
        """
        Choose a subordinate among the list of subordinates, and make it play.
        :return: A subordinate among the list of subordinates.
        """

    def reset(self):
        super().reset()
        self._subordinate_context = {}
        self._is_changing_context = False
        self.add_shared('env', Env())
        self.add_shared('camera', Camera())


class AgentContext:
    def __init__(self):

        self.camera = Point()