# Path: strips/operators.py
# class Action(Operator): 
#     cost = 1 # TODO: cost function
# 
# Path: strips/states.py
# class Literal(object):
# class State(object):
# class PartialState(object):
#     def __init__(self, *args):
#     def negated(self):
#     def copy(self):
#     def positive(self):
#     def negate(self):
#     def __iter__(self):
#     def __eq__(self, other):
#     def __ne__(self, other):
#     def __hash__(self):
#     def __lt__(self, other):
#     def __str__(self):
#     def __init__(self, atoms, external=None):
#     def identity(self):
#     def holds(self, literal):
#     def __iter__(self):
#     def __eq__(self, other):
#     def __ne__(self, other):
#     def __hash__(self):
#     def __str__(self):
#     def __init__(self, literals, test=lambda state: True):
#     def contains(self, state):
#     def __iter__(self):
#     def __eq__(self, other):
#     def __ne__(self, other):
#     def __hash__(self):
#     def __str__(self):
# 
# Path: misc/utils.py
# SEPARATOR = '\n'+85*'-'+'\n'
# def arg_info(frame, ignore=['self']):
# def function_name(stack): # NOTE - stack = inspect.stack()
# def get_path(frame):
# def get_directory(abs_path):
# def global_fn(name):
# def refresh(module_name):
# 
# Path: misc/functions.py
# def pairs(lst):
#   return zip(lst[:-1], lst[1:])


from strips.operators import Action
from strips.states import State, PartialState, Literal, STRIPSProblem
from misc.utils import arg_info, currentframe
from misc.functions import pairs
from itertools import permutations
    blocks = ['Block{}'.format(i) for i in range(1, n+1)]

    operators = [Pick(item) for item in blocks] + \
        [Place(item) for item in blocks] + \
        [Unstack(*item) for item in permutations(blocks, 2)] + \
        [Stack(*item) for item in permutations(blocks, 2)]

    initial = State({OnTable(block) for block in blocks} |
                    {Clear(block) for block in blocks} |
                    {ArmEmpty()})

    tower = blocks[:height]
    goal = PartialState({OnTable(blocks[0]), ArmEmpty()} |
                        {On(obj, under_obj) for under_obj, obj in pairs(tower)})

    return STRIPSProblem(initial, goal, operators)

def restack_blocks(n=5, height=5):
    height = max(height, 0)
    n = max(height, n)
    blocks = ['Block{}'.format(i) for i in range(1, n+1)]

    operators = [Pick(item) for item in blocks] + \
        [Place(item) for item in blocks] + \
        [Unstack(*item) for item in permutations(blocks, 2)] + \
        [Stack(*item) for item in permutations(blocks, 2)]

    tower = blocks[:height]
    table = blocks[height:]
    initial = State({OnTable(blocks[height-1]), ArmEmpty(), Clear(blocks[0])} |

# Path: strips/operators.py
# class Action(Operator): 
#     cost = 1 # TODO: cost function
# 
# Path: strips/states.py
# class Literal(object):
# class State(object):
# class PartialState(object):
#     def __init__(self, *args):
#     def negated(self):
#     def copy(self):
#     def positive(self):
#     def negate(self):
#     def __iter__(self):
#     def __eq__(self, other):
#     def __ne__(self, other):
#     def __hash__(self):
#     def __lt__(self, other):
#     def __str__(self):
#     def __init__(self, atoms, external=None):
#     def identity(self):
#     def holds(self, literal):
#     def __iter__(self):
#     def __eq__(self, other):
#     def __ne__(self, other):
#     def __hash__(self):
#     def __str__(self):
#     def __init__(self, literals, test=lambda state: True):
#     def contains(self, state):
#     def __iter__(self):
#     def __eq__(self, other):
#     def __ne__(self, other):
#     def __hash__(self):
#     def __str__(self):
# 
# Path: misc/utils.py
# SEPARATOR = '\n'+85*'-'+'\n'
# def arg_info(frame, ignore=['self']):
# def function_name(stack): # NOTE - stack = inspect.stack()
# def get_path(frame):
# def get_directory(abs_path):
# def global_fn(name):
# def refresh(module_name):
# 
# Path: misc/functions.py
# def pairs(lst):
#   return zip(lst[:-1], lst[1:])


# Path: strips/domains/blocks_world.py
from strips.operators import Action
from strips.states import State, PartialState, Literal, STRIPSProblem
from misc.utils import arg_info, currentframe
from misc.functions import pairs
from itertools import permutations

    blocks = ['Block{}'.format(i) for i in range(1, n+1)]

    operators = [Pick(item) for item in blocks] + \
        [Place(item) for item in blocks] + \
        [Unstack(*item) for item in permutations(blocks, 2)] + \
        [Stack(*item) for item in permutations(blocks, 2)]

    initial = State({OnTable(block) for block in blocks} |
                    {Clear(block) for block in blocks} |
                    {ArmEmpty()})

    tower = blocks[:height]
    goal = PartialState({OnTable(blocks[0]), ArmEmpty()} |
                        {On(obj, under_obj) for under_obj, obj in pairs(tower)})

    return STRIPSProblem(initial, goal, operators)

def restack_blocks(n=5, height=5):
    height = max(height, 0)
    n = max(height, n)
    blocks = ['Block{}'.format(i) for i in range(1, n+1)]

    operators = [Pick(item) for item in blocks] + \
        [Place(item) for item in blocks] + \
        [Unstack(*item) for item in permutations(blocks, 2)] + \
        [Stack(*item) for item in permutations(blocks, 2)]

    tower = blocks[:height]
    table = blocks[height:]
    initial = State({OnTable(blocks[height-1]), ArmEmpty(), Clear(blocks[0])} |

                    {On(obj, under_obj) for under_obj, obj in pairs(tower[::-1])} |