from __future__ import nested_scopes import string """USAGE: python playgame.py """ # new example successorsDict ={'a':['b','c'],'b':['d','e'],'d':[],\ 'e':[],'c':['f','g','h'],'f':['i','j'],'i':['k','l'],\ 'k':[],'l':[],'j':[],'g':['m','n'],'h':[],'m':[],'n':[]} cutoffvalsDict = {'a':0,'b':0,'c':0,'d':1,\ 'e':1,'f':0,'g':0,'h':1,'i':0,'j':1,'k':1,'l':1,\ 'm':1,'n':1} evalFunDict = {'d':3,'e':5,'h':4,'j':5,'k':0,'l':7,'m':7,'n':8} gameoverDict = {'h':1} # An example from Rich and Knight successorsDict ={'a':['b','c'],'b':['d','e'],'d':[],\ 'e':[],'c':['f','g','h'],'f':['i','j'],'i':['k','l'],\ 'k':[],'l':[],'j':[],'g':['m','n'],'h':[],'m':[],'n':[]} cutoffvalsDict = {'a':0,'b':0,'c':0,'d':1,\ 'e':1,'f':0,'g':0,'h':1,'i':0,'j':1,'k':1,'l':1,\ 'm':1,'n':1} evalFunDict = {'d':3,'e':5,'h':4,'j':5,'k':0,'l':7,'m':7,'n':8} gameoverDict = {'h':1} #Another example: #successorsDict = {'a':['b','q'],'b':['c','j'],'c':['d','g'],\ # 'd':['e','f'],'e':[],'f':[],\ # 'g':['h','i'],'j':['k','n'],'k':['l','m'],\ # 'h':[],'i':[],'l':[],'m':[],'n':['o','p'],'o':[],\ # 'p':[],'q':['r','z'],'r':['s','v'],'z':['z1','z4'],\ # 's':['t','u'],'v':['w','x'],'t':[],'u':[],\ # 'w':[],'x':[],'z1':['z2','z3'],'z4':['z5','z6'],\ # 'z5':[],'z6':[],'z2':[],'z3':[]} # #evalFunDict = {'e':10,'f':11,'h':9,'i':12,'l':14,'m':15,'z1':50,'z4':50,\ # 'o':13,'p':14,'t':15,'a':50,'b':50,'c':50,'d':50,'g':50,'j':50,'z':50,\ # 'r':50,'s':50,'v':50,'q':50,'k':50,'u':2,'n':50,'w':4,'x':1,'z2':3,'z3':22,'z5':24,'z6':25} # #evalFunDict = {'e':10,'f':11,'h':9,'i':12,'l':14,'m':15,\ # 'o':13,'p':14,'t':15,\ # 'u':2,'w':4,'x':1,'z2':3,'z3':22,'z5':24,'z6':25} # #cutoffvalsDict = {'a':0,'b':0,'q':0,'c':0,'j':0,'r':0,\ # 'z':0,'d':0,'g':0,'k':0,'n':0,\ # 's':0,'v':0,'z1':0,'z4':0,'e':1,'f':1,\ # 'h':1,'i':1,'l':1,'m':1,'o':1,'p':1,'t':1,'u':1,\ # 'w':1,'x':1,'z2':1,'z3':1,'z5':1,'z6':1} # #gameoverDict = {} class Node: def __init__ (self,state,parent=None,depth=0): self.state = state self.parent = parent self.depth = depth class Thresh: def __init__(self,initVal,node=None): self.val = initVal self.bestSucc = node def __repr__(self): return str(self.val) + " " + str(self.bestSucc.state) def printGraph(root): printed = {root:1} print root printGraphHelp(printed,root,successorsDict[root],' ') def printGraphHelp(printed,parent,kids,space): for kid in kids: if printed.has_key(kid): print space,parent,"-->",kid,"**Edge to state already printed**" else: printed[kid] = 1 if evalFun(kid,"") > -1: print space + parent + "-->" + kid + " evalFun(" + kid + ") = " + str(evalFun(kid,"")) else: print space + parent + "-->" + kid printGraphHelp(printed,kid,successorsDict[kid],space + ' ') #================ def evalFun(node,space): if evalFunDict.has_key(node): return evalFunDict[node] else: return -1 def cutoff(node,depth,space): return cutoffvalsDict[node] def gameOver(node): return gameoverDict.has_key(node.state) def expand (n, succStates): if succStates == []: return [] else: x = map(lambda s: Node(s,parent=n,depth=1+n.depth),succStates) return x def getUserMove(): print "Your turn; what is your move ", return input(" ? ") def successors(node,space): return successorsDict[node] def playGame(): print "Successor relations:" print successorsDict print "Cutoffs:" print cutoffvalsDict print "EvalFun:" print evalFunDict printGraph('a') initialState = 'a' curNode = Node(initialState) # the initial node result = maxv(curNode,Thresh(-1000),Thresh(1000),0,"") curNode = result.bestSucc while not gameOver(curNode): print "MY MOVE:",curNode.state curNode = Node(getUserMove()) result = maxv(curNode,Thresh(-1000),Thresh(1000),0,"") curNode = result.bestSucc print "Game is over! Result is",evalFun(curNode.state," "), print "for state",curNode.state def maxv (node, parentalpha, parentbeta, depth,space): alpha = Thresh(parentalpha.val,parentalpha.bestSucc) beta = Thresh(parentbeta.val,parentbeta.bestSucc) print space, "maxv", node.state, " alpha:", alpha.val, " beta:", beta.val,"-->" if cutoff(node.state,depth,space): t = Thresh(evalFun(node.state,space),node) print space,"returning",t,"<--" return t else: for s in expand(node,successors(node.state,space)): newspace = space + " " minval = minv(s, alpha, beta, depth+1,newspace) if minval.val > alpha.val: print space, "alpha updated from", alpha.val, "to",minval.val,s.state alpha.val = minval.val alpha.bestSucc = s if alpha.val >= beta.val: print space, "alpha >= beta so returning beta, which is ", beta.val,beta.bestSucc.state,"<--" return beta print space, "returning alpha ", alpha,"<--" return alpha def minv (node, parentalpha, parentbeta, depth, space): alpha = Thresh(parentalpha.val,parentalpha.bestSucc) beta = Thresh(parentbeta.val,parentbeta.bestSucc) print space, "minv",node.state, " alpha:", alpha.val, " beta:", beta.val,"-->" if cutoff(node.state,depth,space): t = Thresh(evalFun(node.state,space),node) print space,"returning",t,"<--" return t else: for s in expand(node,successors(node.state,space)): newspace = space + " " maxval = maxv(s, alpha, beta, depth+1,newspace) if maxval.val < beta.val: print space, "beta updated from", beta.val, "to",maxval.val,s.state beta.val = maxval.val beta.bestSucc = s if beta.val <= alpha.val: print space, "beta <= alpha so returning alpha, which is ", alpha.val,alpha.bestSucc.state,"<--" return alpha print space, "returning beta ", beta return beta playGame()