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
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
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']])
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']]) ])
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']]))
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
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]
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
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)
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)
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)