Rev 424 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/env python__author__ = "Ira W. Snyder (devel@irasnyder.com)"__copyright__ = "Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)"__license__ = "GNU GPL v2 (or, at your option, any later version)"from PyCompat import *from Actions import *from Menu import Menuimport sysimport copyimport random(WALK, PUSH, CLIMB, GRAB) = ('Walk', 'Push', 'Climb', 'Grab')class Possible:def __init__ (self, action, arg1=None, arg2=None):self.action = actionself.arg1 = arg1self.arg2 = arg2def takeAction (self):passdef __eq__ (self, rhs):return (self.action == rhs.action) and (self.arg1 == rhs.arg1) \and (self.arg2 == rhs.arg2)def __repr__ (self):s = '(%s' % self.actionif self.arg1:s += ', %s' % self.arg1if self.arg2:s += ', %s' % self.arg2return '%s)' % sdef generatePossibleMoves (State):moves = []# Grab, Priority 1if Grab(State).meetsPreconditions():moves.append ((1, Possible(GRAB)))# Push, Priority 2for f in LOCATIONS:for t in LOCATIONS:if Push(State, f, t).meetsPreconditions():moves.append ((2, Possible(PUSH, f, t)))# Climb, Priority 2for d in BOX_LOC:if Climb(State, d).meetsPreconditions():moves.append ((2, Possible(CLIMB, d)))# Walk, Priority 3for f in LOCATIONS:for t in LOCATIONS:if Walk(State, f, t).meetsPreconditions():moves.append ((3, Possible(WALK, f, t)))return movesdef chooseMove (moves, priority=None):possible = []# If priority was not set, choose something from the highest# priority that is availableif not priority:if len(moves) > 0:moves.sort()priority = moves[0][0]for e in moves:if e[0] == priority:possible.append (e[1])# Make sure the list is not emptyif len(possible) < 1:return False# Return a random choice from the possible moves of this priorityreturn random.choice (possible)# Return (loop_length, first_instruction_in_loop)def loopDetector (plan_param):plan = copy.deepcopy (plan_param)plan.reverse()isloop = Falsefor i in xrange(len(plan)):cur = plan[:i]rest= plan[i:]for i in xrange(len(cur)):isloop = Trueif cur[i] != rest[i]:isloop = Falsebreakif isloop:return (len(cur), cur[0])return Falsedef findNextMove (State):"""Prioritized Search for the best next move"""poss_moves = generatePossibleMoves(State)chose_move = chooseMove (poss_moves)#print 'POSSIBLE MOVES: ', poss_moves#print 'CHOOSE MOVE: ', chose_movereturn chose_movedef isValidInitialState (State):monkeyPos = Action(State).findMonkeyPosition()boxPos = Action(State).findBoxPosition()onBox = Action(State).monkeyOnBox()if onBox and (monkeyPos != boxPos):return Falsereturn Truedef enter_initial_state ():State = set([])# Get Monkey Positionm = Menu(autorun=True, name='Enter Monkey Position')m.add_entry ('1', 'Window', lambda: WINDOW)m.add_entry ('2', 'Door', lambda: DOOR)m.add_entry ('3', 'Middle', lambda: MIDDLE)m.add_entry ('Q', 'Quit', sys.exit)pos = m.run_menu()[1]State.add ('At(Monkey,%s)' % pos)# Get Box Positionm = Menu(autorun=True, name='Enter Box Position')m.add_entry ('1', 'Window', lambda: WINDOW)m.add_entry ('2', 'Door', lambda: DOOR)m.add_entry ('3', 'Middle', lambda: MIDDLE)m.add_entry ('Q', 'Quit', sys.exit)pos = m.run_menu()[1]State.add ('At(Box,%s)' % pos)# Get Monkey Statusm = Menu(autorun=True, name='Enter Monkey Height Status')m.add_entry ('1', 'Monkey on Box', lambda: 'OnBox()')m.add_entry ('2', 'Monkey on Floor', lambda: 'OnFloor()')m.add_entry ('Q', 'Quit', sys.exit)State.add (m.run_menu()[1])# Get Banana Statusm = Menu(autorun=True, name='Enter Banana Status')m.add_entry ('1', 'Monkey has Banana', lambda: 'HasBanana()')m.add_entry ('2', 'Monkey does not have Banana', lambda: 'NoBanana()')m.add_entry ('Q', 'Quit', sys.exit)State.add (m.run_menu()[1])return Statedef find_plan (State):if not isValidInitialState (State):print 'Bad initial state\n'returnif Action(State).isGoal():print 'Initial State is already a goal state\n'returnprint 'Plan:'while not Action(State).isGoal():next = findNextMove (State)action = next.actionarg1 = next.arg1arg2 = next.arg2if action == WALK:print '%s from %s to %s' % (action, arg1, arg2)State = Walk(State, arg1, arg2).takeAction()elif action == PUSH:print '%s Box from %s to %s' % (action, arg1, arg2)State = Push(State, arg1, arg2).takeAction ()elif action == CLIMB:print '%s %s' % (action, arg1)State = Climb(State, arg1).takeAction()elif action == GRAB:print '%s Banana' % actionState = Grab(State).takeAction()else:print 'BAD STATE'returndef main ():# Create the main menum = Menu (name='Main Menu')m.add_entry ('1', 'Enter Initial State', enter_initial_state)m.add_entry ('2', 'Find Plan', find_plan)m.add_entry ('Q', 'Quit', sys.exit)m.hide_entry ('2')# Run the menuwhile True:(num, func) = m.run_menu ()if num == '1':State = func()m.unhide_entry ('2')elif num == '2':func(copy.deepcopy(State))else:func()if __name__ == '__main__':main ()# vim: set ts=4 sts=4 sw=4: