Example #1
0
def constraints(domain, problem):
    clause_list = []
    # Parser
    parser = PDDL_Parser()
    parser.parse_domain(domain)
    parser.parse_problem(problem)

    state = parser.state
    # Initial state clauses:
    initial_clauses = list(state)
    #print(initial_clauses)

    goal_pos = parser.positive_goals
    goal_not = parser.negative_goals
    goal_clauses = [goal_pos, goal_not]

    action_list = []
    # Grounding process
    ground_actions = []
    for action in parser.actions:
        for act in action.groundify(parser.objects):
            ground_actions.append(act)
    # Appending grounded actions:
    for act in ground_actions:
        action_list.append(act)
        #print(act)
    action_list.append(Action('noop', (), [], [], [], []))
    # Appending to one list:
    clause_list.append(initial_clauses)
    clause_list.append(goal_clauses)
    clause_list.extend(action_list)
    return clause_list
Example #2
0
 def solve(self, domain, problem):
     # Parser
     parser = PDDL_Parser()
     parser.parse_domain(domain)
     parser.parse_problem(problem)
     # Parsed data
     actions = parser.actions
     state = parser.state
     goal_pos = parser.positive_goals
     goal_not = parser.negative_goals
     # Do nothing
     if self.applicable(state, goal_pos, goal_not):
         return []
     # Search
     visited = [state]
     fringe = [state, None]
     while fringe:
         state = fringe.pop(0)
         plan = fringe.pop(0)
         for act in actions:
             if self.applicable(state, act.positive_preconditions,
                                act.negative_preconditions):
                 new_state = self.apply(state, act.add_effects,
                                        act.del_effects)
                 if new_state not in visited:
                     if self.applicable(new_state, goal_pos, goal_not):
                         full_plan = [act]
                         while plan:
                             act, plan = plan
                             full_plan.insert(0, act)
                         return full_plan
                     visited.append(new_state)
                     fringe.append(new_state)
                     fringe.append((act, plan))
     return None
Example #3
0
 def test_parse_problem(self):
     parser = PDDL_Parser()
     parser.parse_domain('examples/dinner/dinner.pddl')
     parser.parse_problem('examples/dinner/pb1.pddl')
     self.assertEqual(parser.problem_name, 'pb1')
     self.assertEqual(parser.objects, {})
     self.assertEqual(parser.state, [['garbage'],['clean'],['quiet']])
     self.assertEqual(parser.positive_goals, [['dinner'], ['present']])
     self.assertEqual(parser.negative_goals, [['garbage']])
Example #4
0
 def test_parse_domain(self):
     parser = PDDL_Parser()
     parser.parse_domain('dinner/dinner.pddl')
     self.assertEqual(parser.domain_name, 'dinner')
     self.assertEqual(parser.requirements, [':strips'])
     self.assertEqual(parser.types, [])
     self.assertEqual(parser.actions, [
         Action('cook', [], [['clean']], [], [['dinner']], []),
         Action('wrap', [], [['quiet']], [], [['present']], []),
         Action('carry', [], [['garbage']], [], [],
                [['garbage'], ['clean']]),
         Action('dolly', [], [['garbage']], [], [],
                [['garbage'], ['quiet']])
     ])
Example #5
0
    def test_parse_problem(self):
        def frozenset_of_tuples(data):
            return frozenset([tuple(t) for t in data])

        parser = PDDL_Parser()
        parser.parse_domain('examples/dinner/dinner.pddl')
        parser.parse_problem('examples/dinner/pb1.pddl')
        self.assertEqual(parser.problem_name, 'pb1')
        self.assertEqual(parser.objects, {})
        self.assertEqual(
            parser.state,
            frozenset_of_tuples([['garbage'], ['clean'], ['quiet']]))
        self.assertEqual(parser.positive_goals,
                         frozenset_of_tuples([['dinner'], ['present']]))
        self.assertEqual(parser.negative_goals,
                         frozenset_of_tuples([['garbage']]))
Example #6
0
def constraints(domain, problem):
    gate_list = []
    # Parser
    parser = PDDL_Parser()
    parser.parse_domain(domain)
    parser.parse_problem(problem)

    state = parser.state
    # Initial state gate:
    initial_gate = list(state)
    #initial_gate = refine_gate(initial_gate)
    #print(initial_gate)

    goal_pos = parser.positive_goals
    goal_not = parser.negative_goals
    goal_gate = [goal_pos, goal_not]
    #goal_gate = [refine_gate(goal_pos), refine_gate(goal_not)]
    #print(goal_gate)

    #for act in parser.actions:
    #  #print(act)
    #  act.positive_preconditions = refine_gate(act.positive_preconditions)
    #  act.negative_preconditions = refine_gate(act.negative_preconditions)
    #  act.add_effects = refine_gate(act.add_effects)
    #  act.del_effects = refine_gate(act.del_effects)
    #  #print(act)

    action_list = []
    # Grounding process
    ground_actions = []
    for action in parser.actions:
        for act in action.groundify(parser.objects):
            ground_actions.append(act)
    # Appending grounded actions:
    for act in ground_actions:
        action_list.append(act)
        #print(act)

    # Appending to one list:
    gate_list.append(initial_gate)
    gate_list.append(goal_gate)
    gate_list.extend(action_list)
    return gate_list
Example #7
0
 def construct(self, domain, problem):
     # Parser
     parser = PDDL_Parser()
     parser.parse_domain(domain)
     parser.parse_problem(problem)
     # Parsed data
     state = parser.state
     initial_state = convert(state)
     goal_pos = parser.positive_goals
     goal_not = parser.negative_goals
     # Do nothing
     if self.applicable(state, goal_pos, goal_not):
         return []
     # Grounding process
     ground_actions = []
     for action in parser.actions:
         for act in action.groundify(parser.objects):
             ground_actions.append(act)
     # Search
     visited = [state]
     need_visit = [state]
     transitions = dict()
     while need_visit:
         state = need_visit.pop(0)
         transitions[convert(state)] = dict()
         for act in ground_actions:
             if self.applicable(state, act.positive_preconditions,
                                act.negative_preconditions):
                 new_state = self.apply(state, act.add_effects,
                                        act.del_effects)
                 if new_state not in visited:
                     visited.append(new_state)
                     need_visit.append(new_state)
                     transitions[convert(state)][act.name] = convert(
                         new_state)
     return [transitions, initial_state]
Example #8
0
class Domain():
    def __init__(self, domainfile, problemfile):
        self.parser_help = PDDL_Parser()
        self.parser_help.parse_domain(domainfile)
        self.parser_help.parse_problem(problemfile)
        self.domprob = DomainProblem(domainfile, problemfile)
        self.current_state = None  # State object
        self.pos_goal = None  # tuple of literals that need to be true at goal
        self.neg_goal = None  # tuple of literals that need to be false at goal
        self.action_dic = None  # list of actions
        self.objects = None  # list of world objects
        self.reversed_objects = None  # for type of object, list of instances
        self.parser()

    def parser(self):
        world_dic = self.domprob.worldobjects()
        # object list
        obj_dic = dict()
        for obj in world_dic.keys():
            wo = WorldObject(name=obj)
            wo.family = world_dic[obj]
            obj_dic[obj] = wo

        # reversed objects
        self.reversed_objects = defaultdict(list)
        for obj, typ in self.domprob.problem.objects.items():
            self.reversed_objects[typ].append(obj)
        for type, subtypes in self.parser_help.types.items(
        ):  # add reference to subtypes
            for sub in subtypes:
                self.reversed_objects[type] += self.reversed_objects[sub]

        # action list
        action_dic = dict()
        for op in self.domprob.operators():
            my_op = Action(name=op)
            action_dic[op] = my_op
        for op in action_dic.keys():
            operator = self.domprob.domain.operators[op]
            var_names = operator.variable_list.keys()
            var_types = operator.variable_list.values()
            var_combinations = itertools.product(
                *[self.reversed_objects[typ] for typ in var_types])
            for var_list in var_combinations:
                value = dict()
                # ground preconditions and effects
                value["preconditions_pos"] = {
                    prec.ground({
                        name: inst
                        for (name, inst) in zip(var_names, var_list)
                    })
                    for prec in operator.precondition_pos
                }
                value["preconditions_neg"] = {
                    prec.ground({
                        name: inst
                        for (name, inst) in zip(var_names, var_list)
                    })
                    for prec in operator.precondition_neg
                }
                value["effets_pos"] = {
                    prec.ground({
                        name: inst
                        for (name, inst) in zip(var_names, var_list)
                    })
                    for prec in operator.effect_pos
                }
                value["effets_neg"] = {
                    prec.ground({
                        name: inst
                        for (name, inst) in zip(var_names, var_list)
                    })
                    for prec in operator.effect_neg
                }
                action_dic[op].action_dic[tuple(var_list)] = value

                init_state_set = set()

        init_state = self.domprob.initialstate()
        init_state_set = set()
        for state in init_state:
            init_state_set.add(tuple(state.predicate))

        # goal
        self.pos_goal = set(self.parser_help.positive_goals)
        self.neg_goal = set(self.parser_help.negative_goals)

        ## Update ##
        self.current_state = State(true_predicates=init_state_set,
                                   pos_goal_state=self.pos_goal,
                                   neg_goal_state=self.neg_goal)
        self.action_dic = action_dic
        self.objects = obj_dic
Example #9
0
class Engine:
    def __init__(self, domain, problem, logfile='/dev/null'):
        # Parser
        self.parser = PDDL_Parser()
        self.parser.parse_domain(domain)
        self.parser.parse_problem(problem)
        # Parsed data
        self.state = self.parser.state
        self.goal_pos = self.parser.positive_goals
        self.goal_not = self.parser.negative_goals

        self.history = []
        self.movelog = []

        self.logfile = logfile

        self.planner = Planner()
        # Do nothing
        if self.planner.applicable(self.state, self.goal_pos, self.goal_not):
            print('Puzzle is already solved! Double-check your problem file!')

    def parseCellName(self, cellName):
        x, y = cellName[4:].split('_')
        # print(cellName)
        # print(out)
        return int(x), int(y)

    def findPlayer(self):
        for pred in self.state:
            if pred[0] == 'player':
                return self.parseCellName(pred[1])
        raise ValueError('Player not found!')

    def formatPos(self, coords):
        return 'cell{}_{}'.format(coords[0], coords[1])

    def groundAction(self, act, assignment):
        variables = []
        for v, _ in act.parameters:
            variables.append(v)
        pps = act.replace(act.positive_preconditions, variables, assignment)
        nps = act.replace(act.negative_preconditions, variables, assignment)
        aes = act.replace(act.add_effects, variables, assignment)
        des = act.replace(act.del_effects, variables, assignment)
        return Action(act.name, assignment, pps, nps, aes, des)

    def addVec(self, *vecs):
        x = 0
        y = 0
        for u, v in vecs:
            x += u
            y += v
        return (x, y)

    # act must already be grounded (e.g. by self.groundAction)
    def tryAction(self, act, log):
        # print(self.state)
        # print(act.positive_preconditions)
        # print(act.negative_preconditions)
        # print(self.planner.applicable(self.state, act.positive_preconditions, act.negative_preconditions))
        if self.planner.applicable(self.state, act.positive_preconditions,
                                   act.negative_preconditions):
            # log.write(str(self.state) + '\n')
            # log.write(str(act))
            act_str = '(:action ({}))'.format(' '.join(
                [act.name, *act.parameters]))
            self.history.append(self.state)
            self.state = self.planner.apply(self.state, act.add_effects,
                                            act.del_effects)
            # log.write(self.lispState() + '\n\n')
            self.movelog.append('{}\n\n{}\n\n'.format(act_str,
                                                      self.lispState()))
            return True
        else:
            return False

    def lookupAction(self, actName):
        for act in self.parser.actions:
            if act.name == actName:
                return act
        return None

    # Finds the next cell adjacent to curCell in direction direc
    def findNextCell(self, curCell, direc):
        for cell in self.parser.objects['cell']:
            if self.planner.applicable(self.state,
                                       [['in-dir', direc, curCell, cell]], []):
                return cell
        return None

    def doMove(self, key, log):
        if key == 'u':
            if len(self.history) >= 1:
                self.state = self.history.pop()
                self.movelog.pop()
            return True
        elif key == 'r':
            self.state = self.parser.state
            # self.history.append(self.state)
            self.history = [self.state]
            self.movelog = []
            return True
        # else:
        #     # log.write('Unparseable input: {}\n\n'.format(key))
        #     return False
        # print(key, delta, actions)
        playerPos = self.findPlayer()
        # print(key, currentCell)
        for act in self.parser.actions:
            currentCell = self.formatPos(playerPos)
            assignment = [key]
            while len(assignment) < len(act.parameters):
                assignment.append(currentCell)
                currentCell = self.findNextCell(
                    currentCell, key
                )  # Having to do this for every cell parameter in every action is inefficient; maybe improve later?
            gact = self.groundAction(act, assignment)
            # print(gact)
            if self.tryAction(gact, log):
                return True
        return False

        # nextCell = self.formatPos(self.addVec(playerPos, delta))
        # afterCell = self.formatPos(self.addVec(playerPos, delta, delta))
        # # print(playerPos, playerCell, nextCell, afterCell)
        # act = self.lookupAction(actions[0])
        # gact = self.groundAction(act, [playerCell, nextCell])
        # # print(gact)
        # if self.tryAction(gact, log):
        #     return True
        # else:
        #     act = self.lookupAction(actions[1])
        #     gact = self.groundAction(act, [playerCell, nextCell, afterCell])
        #     # print(gact)
        #     if self.tryAction(gact, log):
        #         return True
        # # log.write('Blocked move: {}\n\n'.format(actions))
        # return False

    predIDs = {'wall': 1, 'player': 2, 'ball': 4, 'pit': 8, 'goal': 16}

    tiles = {
        0: '  ',  # Floor
        1: '[]',  # Wall
        2: ':)',  # Player
        4: '()',  # Boulder
        8: '\/',  # Pit
        16: '//',  # Goal
        18: '%)',  # Goal and player
        20: '{}'
    }  # Goal and boulder

    def render(self):
        w, h = 0, 0
        for cell in self.parser.objects['cell']:
            x, y = self.parseCellName(cell)
            w = max(w, x + 1)
            h = max(h, y + 1)
        for y in range(h):
            for x in range(w):
                cell = self.formatPos((x, y))
                code = 0
                # print(cell)
                # print(self.state)
                for pred, pid in self.predIDs.items():
                    if self.planner.applicable(self.state, [[pred, cell]], []):
                        code += pid
                if self.planner.applicable(self.goal_pos, [['ball', cell]],
                                           []):
                    code += self.predIDs['goal']
                print(self.tiles[code], end='')
                # if self.planner.applicable(self.state, [['wall', cell]], []):
                #     code = -1
                # else:
                #     if self.planner.applicable(self.state, [['floor', cell]], []):
                #         code = 1
                #     if self.planner.applicable(self.state, [['ball', cell]], []):
                #         code += 2
                #     if self.planner.applicable(self.goal_pos, [['ball', cell]], []):
                #         code += 4
                #     if self.planner.applicable(self.state, [['player', cell]], []):
                #         code += 8
            print()

    def lispState(self, word=':state'):
        out = []
        out.append('({}'.format(word))
        for pred in self.state:
            out.append(' (')
            out.append(' '.join(pred))
            out.append(')')
        out.append(')')
        return ''.join(out)

    def gameloop(self):
        with open(self.logfile, 'w') as log:
            # log.write('{}\n\n'.format(datetime.datetime.now()))
            log.write('(trajectory\n\n')
            log.write('(:objects ')
            for t, os in self.parser.objects.items():
                for o in os:
                    log.write('{} -  {} '.format(o, t))
            log.write(')\n\n')
            log.write(self.lispState(':init'))
            log.write('\n\n')
            while True:
                self.render()
                if self.planner.applicable(self.state, self.goal_pos,
                                           self.goal_not):
                    print('Winningness!')
                    log.write(''.join(self.movelog))
                    log.write(')')
                    return
                prevTime = time.time()
                key = input(
                    'Choose direction ({}ur, followed by Enter): '.format(
                        ''.join(self.parser.objects['dir'])))
                # log.write('{}\n\n'.format(time.time() - prevTime))
                self.doMove(key, log)
Example #10
0
class Engine:

    # Params:
    #   domain: Name of domain file; should be 'soko3/soko3/pddl'
    #   problem: Name of problem file encoding the level to be played, e.g. soko3/levelp3.pddl
    #   logfile: Name of file the trajectory should be written to; defaults to /dev/null
    #   verbose: If true, will write restarts, undoes, and failed moves to the trajectory file
    def __init__(self, domain, problem, logfile='/dev/null', verbose=False):
        # Parser
        self.parser = PDDL_Parser()
        self.parser.parse_domain(domain)
        self.parser.parse_problem(problem)
        # Parsed data
        self.state = self.parser.state
        self.goal_pos = self.parser.positive_goals
        self.goal_not = self.parser.negative_goals

        self.history = []
        self.movelog = []

        self.logfile = logfile
        self.verbose = verbose

        self.planner = Planner()
        # Do nothing
        if self.planner.applicable(self.state, self.goal_pos, self.goal_not):
            print('Puzzle is already solved! Double-check your problem file!')

    def parseCellName(self, cellName):
        _, x, y = cellName.split('-')
        # print(cellName)
        # print(out)
        return int(x), int(y)

    def findPlayer(self):
        for pred in self.state:
            if pred[0] == 'at' and pred[1] == 'player-01':
                return self.parseCellName(pred[2])
        raise ValueError('Player not found!')

    def formatPos(self, coords):
        return 'pos-{:02}-{:02}'.format(coords[0], coords[1])

    def groundAction(self, act, assignment):
        variables = []
        for v, _ in act.parameters:
            variables.append(v)
        pps = act.replace(act.positive_preconditions, variables, assignment)
        nps = act.replace(act.negative_preconditions, variables, assignment)
        aes = act.replace(act.add_effects, variables, assignment)
        des = act.replace(act.del_effects, variables, assignment)
        return Action(act.name, assignment, pps, nps, aes, des)

    def addVec(self, *vecs):
        x = 0
        y = 0
        for u, v in vecs:
            x += u
            y += v
        return (x, y)

    # act must already be grounded (e.g. by self.groundAction)
    def tryAction(self, act, log):
        # print(self.state)
        # print(act.positive_preconditions)
        # print(act.negative_preconditions)
        # print(self.planner.applicable(self.state, act.positive_preconditions, act.negative_preconditions))
        if self.planner.applicable(self.state, act.positive_preconditions,
                                   act.negative_preconditions):
            success = True
            suffix = ''
        else:
            success = False
            suffix = '-failed'
        if success or self.verbose:
            # log.write(str(self.state) + '\n')
            # log.write(str(act))
            print('Action: {} {}'.format(act.name, act.parameters))
            try:
                act_str = '(:action{} ({}))'.format(
                    suffix, ' '.join([act.name, *act.parameters]))
                if success:
                    self.history.append(self.state)
                    self.state = self.planner.apply(self.state,
                                                    act.add_effects,
                                                    act.del_effects)
                # log.write(self.lispState() + '\n\n')
                self.movelog.append('{}\n\n{}\n\n'.format(
                    act_str, self.lispState()))
            except TypeError:
                # Tried to move or push a boulder off the grid or into a wall (in sokoban-sequential, those are the same thing).
                # This can only be a failed action, but trying to log it crashes this script (hence this try-except block), and would cause problems for trajectory.py down the line.
                # So, don't attempt to log this action.
                # This might come back to bite me later, but I'll cross that bridge when I get there.
                pass
        return success

    def lookupAction(self, actName):
        for act in self.parser.actions:
            if act.name == actName:
                return act
        return None

    # Finds the next cell adjacent to curCell in direction direc
    def findNextCell(self, curCell, direc):
        for cell in self.parser.objects['location']:
            if self.planner.applicable(self.state,
                                       [['move-dir', curCell, cell, direc]],
                                       []):
                return cell
        return None

    def getStone(self, cell):
        for stone in self.parser.objects['stone']:
            if self.planner.applicable(self.state, [['at', stone, cell]], []):
                return stone
        return None

    def doMove(self, key, log):
        direc = None
        if key == 'u':
            if len(self.history) >= 1:
                self.state = self.history.pop()
                if self.verbose:
                    self.movelog.append('(:undo)\n\n{}\n\n'.format(
                        self.lispState()))
                else:
                    self.movelog.pop()
            return True
        elif key == 'r':
            self.state = self.parser.state
            # self.history.append(self.state)
            self.history = [self.state]
            if self.verbose:
                self.movelog.append('(:restart)\n\n{}\n\n'.format(
                    self.lispState()))
            else:
                self.movelog = []
            return True
        elif key == 'w':
            direc = 'dir-up'
        elif key == 's':
            direc = 'dir-down'
        elif key == 'a':
            direc = 'dir-left'
        elif key == 'd':
            direc = 'dir-right'
        else:
            # log.write('Unparseable input: {}\n\n'.format(key))
            return False
        # print(key, delta, actions)
        playerPos = self.findPlayer()
        # print(key, currentCell)

        # Put player's cell, next cell, and cell after in a list
        cells = [self.formatPos(playerPos)]
        cells.append(self.findNextCell(cells[0], direc))
        cells.append(self.findNextCell(cells[1], direc))

        # Try move action
        assignment = ['player-01']
        assignment.extend(cells[0:2])
        assignment.append(direc)
        gact = self.groundAction(self.lookupAction('move'), assignment)
        if self.tryAction(gact, log):
            return True
        # If that failed, try push-to-nongoal
        assignment.insert(1, self.getStone(cells[1]))
        assignment.insert(4, cells[2])
        gact = self.groundAction(self.lookupAction('push-to-goal'), assignment)
        if self.tryAction(gact, log):
            return True
        # And if that failed, try push-to-goal
        gact = self.groundAction(self.lookupAction('push-to-nongoal'),
                                 assignment)
        if self.tryAction(gact, log):
            return True
        return False

        # for act in self.parser.actions:
        #     currentCell = self.formatPos(playerPos)
        #     assignment = [key]
        #     while len(assignment) < len(act.parameters):
        #         assignment.append(currentCell)
        #         currentCell = self.findNextCell(currentCell, key)    # Having to do this for every cell parameter in every action is inefficient; maybe improve later?
        #     gact = self.groundAction(act, assignment)
        #     # print(gact)
        #     if self.tryAction(gact, log):
        #         return True
        # return False

        # nextCell = self.formatPos(self.addVec(playerPos, delta))
        # afterCell = self.formatPos(self.addVec(playerPos, delta, delta))
        # # print(playerPos, playerCell, nextCell, afterCell)
        # act = self.lookupAction(actions[0])
        # gact = self.groundAction(act, [playerCell, nextCell])
        # # print(gact)
        # if self.tryAction(gact, log):
        #     return True
        # else:
        #     act = self.lookupAction(actions[1])
        #     gact = self.groundAction(act, [playerCell, nextCell, afterCell])
        #     # print(gact)
        #     if self.tryAction(gact, log):
        #         return True
        # # log.write('Blocked move: {}\n\n'.format(actions))
        # return False

    predIDs = {'wall': 1, 'player': 2, 'ball': 4, 'pit': 8, 'goal': 16}

    tiles = {
        0: '  ',  # Floor
        1: '[]',  # Wall
        2: ':)',  # Player
        4: '()',  # Boulder
        8: '\/',  # Pit
        16: '//',  # Goal
        18: '%)',  # Goal and player
        20: '{}'
    }  # Goal and boulder

    nonwalls = set()

    def findNonWalls(self):
        for pred in self.state:
            # print('Checking {}'.format(pred))
            if pred[0] == 'move-dir':
                self.nonwalls.add(pred[1])
                self.nonwalls.add(pred[2])

    def renderCell(self, cell):
        if cell not in self.nonwalls:
            return '[]'
        elif self.formatPos(self.findPlayer()) == cell:
            if self.planner.applicable(self.state, [['is-goal', cell]], []):
                return '%)'
            else:
                return ':)'
        elif self.getStone(cell) is not None:
            if self.planner.applicable(self.state, [['is-goal', cell]], []):
                return '{}'
            else:
                return '()'
        else:
            if self.planner.applicable(self.state, [['is-goal', cell]], []):
                return '//'
            else:
                return '  '

    def render(self):
        w, h = 0, 0
        for cell in self.parser.objects['location']:
            x, y = self.parseCellName(cell)
            w = max(w, x + 1)
            h = max(h, y + 1)
        for y in range(1, h):
            for x in range(1, w):
                cell = self.formatPos((x, y))
                # code = 0
                # # print(cell)
                # # print(self.state)
                # for pred, pid in self.predIDs.items():
                #     if self.planner.applicable(self.state, [[pred, cell]], []):
                #         code += pid
                # if self.planner.applicable(self.goal_pos, [['ball', cell]], []):
                #     code += self.predIDs['goal']
                print(self.renderCell(cell), end='')
                # if self.planner.applicable(self.state, [['wall', cell]], []):
                #     code = -1
                # else:
                #     if self.planner.applicable(self.state, [['floor', cell]], []):
                #         code = 1
                #     if self.planner.applicable(self.state, [['ball', cell]], []):
                #         code += 2
                #     if self.planner.applicable(self.goal_pos, [['ball', cell]], []):
                #         code += 4
                #     if self.planner.applicable(self.state, [['player', cell]], []):
                #         code += 8
            print()

    def lispState(self, word=':state'):
        out = []
        out.append('({}'.format(word))
        for pred in self.state:
            out.append(' (')
            out.append(' '.join(pred))
            out.append(')')
        out.append(')')
        return ''.join(out)

    def gameloop(self):
        with open(self.logfile, 'w') as log:
            # log.write('{}\n\n'.format(datetime.datetime.now()))
            log.write('(trajectory\n\n')
            log.write('(:objects ')
            for t, os in self.parser.objects.items():
                for o in os:
                    log.write('{} -  {} '.format(o, t))
            log.write(')\n\n')
            log.write(self.lispState(':init'))
            log.write('\n\n')
            self.findNonWalls()
            while True:
                self.render()
                if self.planner.applicable(self.state, self.goal_pos,
                                           self.goal_not):
                    print('Winningness!')
                    log.write(''.join(self.movelog))
                    log.write(')')
                    return
                prevTime = time.time()
                key = input('Choose direction (wasdur, followed by Enter): ')
                # log.write('{}\n\n'.format(time.time() - prevTime))
                self.doMove(key, log)
Example #11
0
class Engine:
    def __init__(self, domain, problem, logfile='/dev/null'):
        # Parser
        self.parser = PDDL_Parser()
        self.parser.parse_domain(domain)
        self.parser.parse_problem(problem)
        # Parsed data
        self.state = self.parser.state
        self.goal_pos = self.parser.positive_goals
        self.goal_not = self.parser.negative_goals

        self.history = []
        self.movelog = []

        self.logfile = logfile

        self.planner = Planner()
        # Do nothing
        if self.planner.applicable(self.state, self.goal_pos, self.goal_not):
            print('Puzzle is already solved! Double-check your problem file!')

    def parseCellName(self, cellName):
        x, y = cellName[4:].split('_')
        # print(cellName)
        # print(out)
        return int(x), int(y)

    def findPlayer(self):
        for pred in self.state:
            if pred[0] == 'player':
                return self.parseCellName(pred[1])
        raise ValueError('Player not found!')

    def formatPos(self, coords):
        return 'cell{}_{}'.format(coords[0], coords[1])

    def groundAction(self, act, assignment):
        variables = []
        for v, _ in act.parameters:
            variables.append(v)
        pps = act.replace(act.positive_preconditions, variables, assignment)
        nps = act.replace(act.negative_preconditions, variables, assignment)
        aes = act.replace(act.add_effects, variables, assignment)
        des = act.replace(act.del_effects, variables, assignment)
        return Action(act.name, assignment, pps, nps, aes, des)

    def addVec(self, *vecs):
        x = 0
        y = 0
        for u, v in vecs:
            x += u
            y += v
        return (x, y)

    # act must already be grounded (e.g. by self.groundAction)
    def tryAction(self, act, log):
        # print(self.state)
        # print(act.positive_preconditions)
        # print(act.negative_preconditions)
        # print(self.planner.applicable(self.state, act.positive_preconditions, act.negative_preconditions))
        if self.planner.applicable(self.state, act.positive_preconditions,
                                   act.negative_preconditions):
            # log.write(str(self.state) + '\n')
            # log.write(str(act))
            act_str = '(:action ({}))'.format(' '.join(
                [act.name, *act.parameters]))
            self.history.append(self.state)
            self.state = self.planner.apply(self.state, act.add_effects,
                                            act.del_effects)
            # log.write(self.lispState() + '\n\n')
            self.movelog.append('{}\n\n{}\n\n'.format(act_str,
                                                      self.lispState()))
            return True
        else:
            return False

    def lookupAction(self, actName):
        for act in self.parser.actions:
            if act.name == actName:
                return act
        return None

    def doMove(self, key, log):
        delta = None
        actions = []
        if key == 'w':
            delta = (0, -1)
            actions = ['movenorth', 'pushnorth']
        elif key == 'a':
            delta = (-1, 0)
            actions = ['movewest', 'pushwest']
        elif key == 's':
            delta = (0, 1)
            actions = ['movesouth', 'pushsouth']
        elif key == 'd':
            delta = (1, 0)
            actions = ['moveeast', 'pusheast']
        elif key == 'u':
            if len(self.history) >= 1:
                self.state = self.history.pop()
                self.movelog.pop()
            return True
        elif key == 'r':
            self.state = self.parser.state
            # self.history.append(self.state)
            self.history = [self.state]
            self.movelog = []
            return True
        else:
            # log.write('Unparseable input: {}\n\n'.format(key))
            return False
        # print(key, delta, actions)
        playerPos = self.findPlayer()
        playerCell = self.formatPos(playerPos)
        nextCell = self.formatPos(self.addVec(playerPos, delta))
        afterCell = self.formatPos(self.addVec(playerPos, delta, delta))
        # print(playerPos, playerCell, nextCell, afterCell)
        act = self.lookupAction(actions[0])
        gact = self.groundAction(act, [playerCell, nextCell])
        # print(gact)
        if self.tryAction(gact, log):
            return True
        else:
            act = self.lookupAction(actions[1])
            gact = self.groundAction(act, [playerCell, nextCell, afterCell])
            # print(gact)
            if self.tryAction(gact, log):
                return True
        # log.write('Blocked move: {}\n\n'.format(actions))
        return False

    tiles = {
        -1: '[]',  # Wall
        1: '  ',  # Floor
        3: '()',  # Boulder on floor
        5: '//',  # Goal on floor
        7: '{}',  # Goal and boulder on floor
        9: ':)',  # Player on floor
        13: '%)'
    }  # Goal and player on floor

    def render(self):
        w, h = 0, 0
        for cell in self.parser.objects['object']:
            x, y = self.parseCellName(cell)
            w = max(w, x + 1)
            h = max(h, y + 1)
        for y in range(h):
            for x in range(w):
                cell = self.formatPos((x, y))
                code = 0
                # print(cell)
                # print(self.state)
                if self.planner.applicable(self.state, [['wall', cell]], []):
                    code = -1
                else:
                    if self.planner.applicable(self.state, [['floor', cell]],
                                               []):
                        code = 1
                    if self.planner.applicable(self.state, [['ball', cell]],
                                               []):
                        code += 2
                    if self.planner.applicable(self.goal_pos, [['ball', cell]],
                                               []):
                        code += 4
                    if self.planner.applicable(self.state, [['player', cell]],
                                               []):
                        code += 8
                print(self.tiles[code], end='')
            print()

    def lispState(self, word=':state'):
        out = []
        out.append('({}'.format(word))
        for pred in self.state:
            out.append(' (')
            out.append(' '.join(pred))
            out.append(')')
        out.append(')')
        return ''.join(out)

    def gameloop(self):
        with open(self.logfile, 'w') as log:
            # log.write('{}\n\n'.format(datetime.datetime.now()))
            log.write('(trajectory\n\n')
            log.write('(:objects ')
            for t, os in self.parser.objects.items():
                for o in os:
                    log.write('{} -  {} '.format(o, t))
            log.write(')\n\n')
            log.write(self.lispState(':init'))
            log.write('\n\n')
            while True:
                self.render()
                if self.planner.applicable(self.state, self.goal_pos,
                                           self.goal_not):
                    print('Winningness!')
                    log.write(''.join(self.movelog))
                    log.write(')')
                    return
                prevTime = time.time()
                key = input('Choose direction (wasdur, followed by Enter): ')
                # log.write('{}\n\n'.format(time.time() - prevTime))
                self.doMove(key, log)