multiprocessing and games

Brian Blais bblais at bryant.edu
Sat Feb 13 23:32:15 CET 2010


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
bblais at 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()


  
    
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20100213/9cd614bb/attachment.html>


More information about the Python-list mailing list