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

Reply via email to