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 Menu
import sys
import copy
import random
(WALK, PUSH, CLIMB, GRAB) = ('Walk', 'Push', 'Climb', 'Grab')
class Possible:
def __init__ (self, action, arg1=None, arg2=None):
self.action = action
self.arg1 = arg1
self.arg2 = arg2
def takeAction (self):
pass
def __eq__ (self, rhs):
return (self.action == rhs.action) and (self.arg1 == rhs.arg1) \
and (self.arg2 == rhs.arg2)
def __repr__ (self):
s = '(%s' % self.action
if self.arg1:
s += ', %s' % self.arg1
if self.arg2:
s += ', %s' % self.arg2
return '%s)' % s
def generatePossibleMoves (State):
moves = []
# Grab, Priority 1
if Grab(State).meetsPreconditions():
moves.append ((1, Possible(GRAB)))
# Push, Priority 2
for f in LOCATIONS:
for t in LOCATIONS:
if Push(State, f, t).meetsPreconditions():
moves.append ((2, Possible(PUSH, f, t)))
# Climb, Priority 2
for d in BOX_LOC:
if Climb(State, d).meetsPreconditions():
moves.append ((2, Possible(CLIMB, d)))
# Walk, Priority 3
for f in LOCATIONS:
for t in LOCATIONS:
if Walk(State, f, t).meetsPreconditions():
moves.append ((3, Possible(WALK, f, t)))
return moves
def chooseMove (moves, priority=None):
possible = []
# If priority was not set, choose something from the highest
# priority that is available
if 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 empty
if len(possible) < 1:
return False
# Return a random choice from the possible moves of this priority
return random.choice (possible)
# Return (loop_length, first_instruction_in_loop)
def loopDetector (plan_param):
plan = copy.deepcopy (plan_param)
plan.reverse()
isloop = False
for i in xrange(len(plan)):
cur = plan[:i]
rest= plan[i:]
for i in xrange(len(cur)):
isloop = True
if cur[i] != rest[i]:
isloop = False
break
if isloop:
return (len(cur), cur[0])
return False
def 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_move
return chose_move
def isValidInitialState (State):
monkeyPos = Action(State).findMonkeyPosition()
boxPos = Action(State).findBoxPosition()
onBox = Action(State).monkeyOnBox()
if onBox and (monkeyPos != boxPos):
return False
return True
def enter_initial_state ():
State = set([])
# Get Monkey Position
m = 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 Position
m = 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 Status
m = 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 Status
m = 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 State
def find_plan (State):
if not isValidInitialState (State):
print 'Bad initial state\n'
return
if Action(State).isGoal():
print 'Initial State is already a goal state\n'
return
print 'Plan:'
while not Action(State).isGoal():
next = findNextMove (State)
action = next.action
arg1 = next.arg1
arg2 = next.arg2
if 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' % action
State = Grab(State).takeAction()
else:
print 'BAD STATE'
return
def main ():
# Create the main menu
m = 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 menu
while 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: