On Feb 13, 2010, at 12:54 , MRAB wrote:
Brian Blais wrote:
I've been thinking about implementing some simple games
Forget about global variables, they're not worth it! :-)
Think in terms of messages, sent via pipes, sockets or multiprocessing
queues.
okay...let's make this concrete. given your ideas, I have it working
for the first type of agent, namely one that is called like:
move=agent(board,player)
For a specific example, I'm using the simplest version of a game
called Nim. You start with a number of sticks, players take turns
taking 1, 2, or 3 sticks, and you lose if you take the last stick.
Two agents for this are:
# agent1.py - simple take 1 agent
def agent(board,player):
return 1
# agent2.py - perfect player
def agent(board,player):
move=(board-1)%4
if move==0:
return 1
else:
return move
I run my simulator like (complete code below):
s=Sim('agent1','agent2')
winner=s.run()
and it spawns two processes, passes messages between the sim and the
agents, and closes the agents nicely when the game is over. I'm not
sure how I catch errors in the agents, especially accidental infinite
loops.
Now the second type of agent is structured differently. I'd like
something like:
# agent3.py - simple take 1 agent
def agent(state):
while True:
Take(1)
# agent4.py - perfect player
def agent(state):
N=state['board'] # get the current information
while True:
move=(N-1)%4
if move==0:
Take(1)
else:
Take(move)
I tried to implement this in the second wrapper below, but I can't
get the agent function to "see" local functions in the wrapper. I
probably need an import somewhere, but I haven't quite figured out
the scoping with multiprocessing, etc...
I include the code below. The two message-passing wrappers are
there, and it works for the first two agents, but not the second two
because of scoping issues.
Is there a better way to be doing this? Are there other examples
like this that I can look at to improve what I am doing?
thanks,
Brian Blais
--
Brian Blais
bbl...@bryant.edu
http://web.bryant.edu/~bblais
http://bblais.blogspot.com/
# testing multiprocessing with games
from __future__ import with_statement
from multiprocessing import Pipe,Process
def wrap_agent(connection,fname):
agent_module = __import__(fname)
end=False
while not end:
state=connection.recv()
if state['done']:
break
move=agent_module.agent(state['board'],state['player'])
connection.send(move)
print "%s done" % fname
connection.close()
def wrap_agent2(connection,fname):
def Take(T):
state1=connection.recv()
state.update(state1)
if state['done']:
raise ValueError # should probably use a custom exception
move=T
connection.send(move)
execfile(fname+".py")
print locals() # seems to appear in locals
state=connection.recv()
if state['done']:
print "%s done" % fname
connection.close()
return
try:
agent(state)
except ValueError:
pass
print "%s done" % fname
connection.close()
class Sim(object):
def __init__(self,agent1,agent2,type=1):
self.agent_files=[agent1,agent2]
self.type=type
def run(self):
self.processes=[]
self.connections=[]
for fname in self.agent_files:
parent,child=Pipe()
self.connections.append(parent)
if self.type==1:
proc=Process(target=wrap_agent, args=(child,fname,))
else:
proc=Process(target=wrap_agent2, args=(child,fname,))
self.processes.append(proc)
for proc in self.processes:
proc.start()
current_player,other_player=1,2
N=23
state={}
while N>1:
state['board']=N
state['player']=current_player
state['done']=False
c=self.connections[current_player-1]
print "Number of sticks: ",N
c.send(state)
move=c.recv()
print "Player ",current_player,"takes ",move
N-=move
current_player,other_player=other_player,current_player
print "Number of sticks: ",N
# send the end signals
state['done']=True
for c in self.connections:
c.send(state)
for p in self.processes:
p.join()
if N==1:
winner=other_player
else:
winner=current_player
print "Winner is ",winner
return winner
if __name__=="__main__":
s=Sim('agent1','agent2')
winner=s.run()
print "============"
s=Sim('agent3','agent4',type=2)
winner=s.run()
--
http://mail.python.org/mailman/listinfo/python-list