# Path: difflogic/envs/blocksworld/envs.py
# class FinalBlocksWorldEnv(BlocksWorldEnv):
#   """The BlocksWorld environment for the final task."""
# 
#   def __init__(self,
#                nr_blocks,
#                random_order=False,
#                shape_only=False,
#                fix_ground=False,
#                prob_unchange=0.0,
#                prob_fall=0.0):
#     super().__init__(nr_blocks, random_order, True, prob_unchange, prob_fall)
#     self.shape_only = shape_only
#     self.fix_ground = fix_ground
# 
#   def _restart(self):
#     self.start_world = randomly_generate_world(
#         self.nr_blocks, random_order=False)
#     self.final_world = randomly_generate_world(
#         self.nr_blocks, random_order=False)
#     self.world = self.start_world
#     if self.random_order:
#       n = self.world.size
#       # Ground is fixed as index 0 if fix_ground is True
#       ground_ind = 0 if self.fix_ground else random.randint(n)
# 
#       def get_order():
#         raw_order = random.permutation(n - 1)
#         order = []
#         for i in range(n - 1):
#           if i == ground_ind:
#             order.append(0)
#           order.append(raw_order[i] + 1)
#         if ground_ind == n - 1:
#           order.append(0)
#         return order
# 
#       self.start_world.blocks.set_random_order(get_order())
#       self.final_world.blocks.set_random_order(get_order())
# 
#     self._prepare_worlds()
#     self.start_state = decorate(
#         self._get_coordinates(self.start_world), self.nr_objects, 0)
#     self.final_state = decorate(
#         self._get_coordinates(self.final_world), self.nr_objects, 1)
# 
#     self.is_over = False
#     self.cached_result = self._get_result()
# 
#   def _prepare_worlds(self):
#     pass
# 
#   def _action(self, action):
#     assert self.start_world is not None, 'you need to call restart() first'
# 
#     if self.is_over:
#       return 0, True
#     r, is_over = self.cached_result
#     if is_over:
#       self.is_over = True
#       return r, is_over
# 
#     x, y = action
#     assert 0 <= x <= self.nr_blocks and 0 <= y <= self.nr_blocks
# 
#     p = random.rand()
#     if p >= self.prob_unchange:
#       if p < self.prob_unchange + self.prob_fall:
#         y = self.start_world.blocks.inv_index(0)  # fall to ground
#       self.start_world.move(x, y)
#       self.start_state = decorate(
#           self._get_coordinates(self.start_world), self.nr_objects, 0)
#     r, is_over = self._get_result()
#     if is_over:
#       self.is_over = True
#     return r, is_over
# 
#   def _get_current_state(self):
#     assert self.start_world is not None, 'Should call restart() first.'
#     return np.vstack([self.start_state, self.final_state])
# 
#   def _get_result(self):
#     sorted_start_state = self._get_coordinates(self.start_world, sort=True)
#     sorted_final_state = self._get_coordinates(self.final_world, sort=True)
#     if (sorted_start_state == sorted_final_state).all():
#       return 1, True
#     else:
#       return 0, False
# 
#   def _get_coordinates(self, world, sort=False):
#     # If shape_only=True, only the shape of the blocks need to be the same.
#     # If shape_only=False, the index of the blocks should also match.
#     coordinates = get_coordinates(world, absolute=not self.shape_only)
#     if sort:
#       if not self.shape_only:
#         coordinates = decorate(coordinates, self.nr_objects, 0)
#       coordinates = np.array(sorted(list(map(tuple, coordinates))))
#     return coordinates
# 
# Path: difflogic/envs/utils.py
# def get_action_mapping_blocksworld(nr_blocks, exclude_self=True):
#   return get_action_mapping_graph(nr_blocks + 1, exclude_self)
# 
# Path: difflogic/envs/utils.py
# class MapActionProxy(ProxyRLEnvBase):
#   """RL Env proxy to map actions using provided mapping function."""
# 
#   def __init__(self, other, mapping):
#     super().__init__(other)
#     self._mapping = mapping
# 
#   @property
#   def mapping(self):
#     return self._mapping
# 
#   def map_action(self, action):
#     assert action < len(self._mapping)
#     return self._mapping[action]
# 
#   def _get_action_space(self):
#     return DiscreteActionSpace(len(self._mapping))
# 
#   def _action(self, action):
#     return self.proxy.action(self.map_action(action))


from jaclearn.rl.proxy import LimitLengthProxy
from .envs import FinalBlocksWorldEnv
from ..utils import get_action_mapping_blocksworld
from ..utils import MapActionProxy
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Quick access for blocksworld environments."""



__all__ = ['get_final_env', 'make']


def get_final_env(nr_blocks,
                  random_order=False,
                  exclude_self=True,
                  shape_only=False,
                  fix_ground=False,
                  limit_length=None):
  """Get the blocksworld environment for the final task."""
  p = FinalBlocksWorldEnv(
      nr_blocks,
      random_order=random_order,
      shape_only=shape_only,
      fix_ground=fix_ground)
  p = LimitLengthProxy(p, limit_length or nr_blocks * 4)

# Path: difflogic/envs/blocksworld/envs.py
# class FinalBlocksWorldEnv(BlocksWorldEnv):
#   """The BlocksWorld environment for the final task."""
# 
#   def __init__(self,
#                nr_blocks,
#                random_order=False,
#                shape_only=False,
#                fix_ground=False,
#                prob_unchange=0.0,
#                prob_fall=0.0):
#     super().__init__(nr_blocks, random_order, True, prob_unchange, prob_fall)
#     self.shape_only = shape_only
#     self.fix_ground = fix_ground
# 
#   def _restart(self):
#     self.start_world = randomly_generate_world(
#         self.nr_blocks, random_order=False)
#     self.final_world = randomly_generate_world(
#         self.nr_blocks, random_order=False)
#     self.world = self.start_world
#     if self.random_order:
#       n = self.world.size
#       # Ground is fixed as index 0 if fix_ground is True
#       ground_ind = 0 if self.fix_ground else random.randint(n)
# 
#       def get_order():
#         raw_order = random.permutation(n - 1)
#         order = []
#         for i in range(n - 1):
#           if i == ground_ind:
#             order.append(0)
#           order.append(raw_order[i] + 1)
#         if ground_ind == n - 1:
#           order.append(0)
#         return order
# 
#       self.start_world.blocks.set_random_order(get_order())
#       self.final_world.blocks.set_random_order(get_order())
# 
#     self._prepare_worlds()
#     self.start_state = decorate(
#         self._get_coordinates(self.start_world), self.nr_objects, 0)
#     self.final_state = decorate(
#         self._get_coordinates(self.final_world), self.nr_objects, 1)
# 
#     self.is_over = False
#     self.cached_result = self._get_result()
# 
#   def _prepare_worlds(self):
#     pass
# 
#   def _action(self, action):
#     assert self.start_world is not None, 'you need to call restart() first'
# 
#     if self.is_over:
#       return 0, True
#     r, is_over = self.cached_result
#     if is_over:
#       self.is_over = True
#       return r, is_over
# 
#     x, y = action
#     assert 0 <= x <= self.nr_blocks and 0 <= y <= self.nr_blocks
# 
#     p = random.rand()
#     if p >= self.prob_unchange:
#       if p < self.prob_unchange + self.prob_fall:
#         y = self.start_world.blocks.inv_index(0)  # fall to ground
#       self.start_world.move(x, y)
#       self.start_state = decorate(
#           self._get_coordinates(self.start_world), self.nr_objects, 0)
#     r, is_over = self._get_result()
#     if is_over:
#       self.is_over = True
#     return r, is_over
# 
#   def _get_current_state(self):
#     assert self.start_world is not None, 'Should call restart() first.'
#     return np.vstack([self.start_state, self.final_state])
# 
#   def _get_result(self):
#     sorted_start_state = self._get_coordinates(self.start_world, sort=True)
#     sorted_final_state = self._get_coordinates(self.final_world, sort=True)
#     if (sorted_start_state == sorted_final_state).all():
#       return 1, True
#     else:
#       return 0, False
# 
#   def _get_coordinates(self, world, sort=False):
#     # If shape_only=True, only the shape of the blocks need to be the same.
#     # If shape_only=False, the index of the blocks should also match.
#     coordinates = get_coordinates(world, absolute=not self.shape_only)
#     if sort:
#       if not self.shape_only:
#         coordinates = decorate(coordinates, self.nr_objects, 0)
#       coordinates = np.array(sorted(list(map(tuple, coordinates))))
#     return coordinates
# 
# Path: difflogic/envs/utils.py
# def get_action_mapping_blocksworld(nr_blocks, exclude_self=True):
#   return get_action_mapping_graph(nr_blocks + 1, exclude_self)
# 
# Path: difflogic/envs/utils.py
# class MapActionProxy(ProxyRLEnvBase):
#   """RL Env proxy to map actions using provided mapping function."""
# 
#   def __init__(self, other, mapping):
#     super().__init__(other)
#     self._mapping = mapping
# 
#   @property
#   def mapping(self):
#     return self._mapping
# 
#   def map_action(self, action):
#     assert action < len(self._mapping)
#     return self._mapping[action]
# 
#   def _get_action_space(self):
#     return DiscreteActionSpace(len(self._mapping))
# 
#   def _action(self, action):
#     return self.proxy.action(self.map_action(action))


# Path: difflogic/envs/blocksworld/quickaccess.py
from jaclearn.rl.proxy import LimitLengthProxy
from .envs import FinalBlocksWorldEnv
from ..utils import get_action_mapping_blocksworld
from ..utils import MapActionProxy

# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Quick access for blocksworld environments."""



__all__ = ['get_final_env', 'make']


def get_final_env(nr_blocks,
                  random_order=False,
                  exclude_self=True,
                  shape_only=False,
                  fix_ground=False,
                  limit_length=None):
  """Get the blocksworld environment for the final task."""
  p = FinalBlocksWorldEnv(
      nr_blocks,
      random_order=random_order,
      shape_only=shape_only,
      fix_ground=fix_ground)
  p = LimitLengthProxy(p, limit_length or nr_blocks * 4)

  mapping = get_action_mapping_blocksworld(nr_blocks, exclude_self=exclude_self)