Fixed networking!
[progcomp2013.git] / qchess / src / player.py
index 3e6faba..99d3616 100644 (file)
@@ -1,7 +1,7 @@
 import subprocess
 import select
 import platform
-
+import re
 
 agent_timeout = -1.0 # Timeout in seconds for AI players to make moves
                        # WARNING: Won't work for windows based operating systems
@@ -15,13 +15,19 @@ class Player():
                self.name = name
                self.colour = colour
 
+       def update(self, result):
+               return result
+
+       def reset_board(self, s):
+               pass
+
 # Player that runs from another process
-class AgentPlayer(Player):
+class ExternalAgent(Player):
 
 
        def __init__(self, name, colour):
                Player.__init__(self, name, colour)
-               self.p = subprocess.Popen(name, stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+               self.p = subprocess.Popen(name,bufsize=0,stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True,universal_newlines=True)
                
                self.send_message(colour)
 
@@ -31,13 +37,13 @@ class AgentPlayer(Player):
                else:
                        ready = [self.p.stdin]
                if self.p.stdin in ready:
-                       #print "Writing to p.stdin"
+                       #sys.stderr.write("Writing \'" + s + "\' to " + str(self.p) + "\n")
                        try:
                                self.p.stdin.write(s + "\n")
                        except:
                                raise Exception("UNRESPONSIVE")
                else:
-                       raise Exception("UNRESPONSIVE")
+                       raise Exception("TIMEOUT")
 
        def get_response(self):
                if agent_timeout > 0.0:
@@ -45,13 +51,15 @@ class AgentPlayer(Player):
                else:
                        ready = [self.p.stdout]
                if self.p.stdout in ready:
-                       #print "Reading from p.stdout"
+                       #sys.stderr.write("Reading from " + str(self.p) + " 's stdout...\n")
                        try:
-                               return self.p.stdout.readline().strip("\r\n")
+                               result = self.p.stdout.readline().strip(" \t\r\n")
+                               #sys.stderr.write("Read \'" + result + "\' from " + str(self.p) + "\n")
+                               return result
                        except: # Exception, e:
                                raise Exception("UNRESPONSIVE")
                else:
-                       raise Exception("UNRESPONSIVE")
+                       raise Exception("TIMEOUT")
 
        def select(self):
 
@@ -59,7 +67,8 @@ class AgentPlayer(Player):
                line = self.get_response()
                
                try:
-                       result = map(int, line.split(" "))
+                       m = re.match("\s*(\d+)\s+(\d+)\s*", line)
+                       result = map(int, [m.group(1), m.group(2)])
                except:
                        raise Exception("GIBBERISH \"" + str(line) + "\"")
                return result
@@ -67,7 +76,7 @@ class AgentPlayer(Player):
        def update(self, result):
                #print "Update " + str(result) + " called for AgentPlayer"
                self.send_message(result)
-
+               return result
 
        def get_move(self):
                
@@ -75,11 +84,19 @@ class AgentPlayer(Player):
                line = self.get_response()
                
                try:
-                       result = map(int, line.split(" "))
+                       m = re.match("\s*(\d+)\s+(\d+)\s*", line)
+                       result = map(int, [m.group(1), m.group(2)])
+
                except:
                        raise Exception("GIBBERISH \"" + str(line) + "\"")
                return result
 
+       def reset_board(self, s):
+               self.send_message("BOARD")
+               for line in s.split("\n"):
+                       self.send_message(line.strip(" \r\n"))
+               self.send_message("END BOARD")
+
        def quit(self, final_result):
                try:
                        self.send_message("QUIT " + final_result)
@@ -145,16 +162,35 @@ class HumanPlayer(Player):
                        pass
                else:
                        sys.stdout.write(result + "\n") 
+               return result
 
 
-# Player that makes random moves
-class AgentRandom(Player):
+# Default internal player (makes random moves)
+class InternalAgent(Player):
        def __init__(self, name, colour):
                Player.__init__(self, name, colour)
                self.choice = None
 
                self.board = Board(style = "agent")
 
+
+
+       def update(self, result):
+               
+               self.board.update(result)
+               #self.board.verify()
+               return result
+
+       def reset_board(self, s):
+               self.board.reset_board(s)
+
+       def quit(self, final_result):
+               pass
+
+class AgentRandom(InternalAgent):
+       def __init__(self, name, colour):
+               InternalAgent.__init__(self, name, colour)
+
        def select(self):
                while True:
                        self.choice = self.board.pieces[self.colour][random.randint(0, len(self.board.pieces[self.colour])-1)]
@@ -179,12 +215,46 @@ class AgentRandom(Player):
                move = moves[random.randint(0, len(moves)-1)]
                return move
 
-       def update(self, result):
-               #sys.stderr.write(sys.argv[0] + " : Update board for AgentRandom\n")
-               self.board.update(result)
-               self.board.verify()
 
-       def quit(self, final_result):
-               pass
+# Terrible, terrible hacks
+
+def run_agent(agent):
+       #sys.stderr.write(sys.argv[0] + " : Running agent " + str(agent) + "\n")
+       while True:
+               line = sys.stdin.readline().strip(" \r\n")
+               if line == "SELECTION?":
+                       #sys.stderr.write(sys.argv[0] + " : Make selection\n")
+                       [x,y] = agent.select() # Gets your agent's selection
+                       #sys.stderr.write(sys.argv[0] + " : Selection was " + str(agent.choice) + "\n")
+                       sys.stdout.write(str(x) + " " + str(y) + "\n")                          
+               elif line == "MOVE?":
+                       #sys.stderr.write(sys.argv[0] + " : Make move\n")
+                       [x,y] = agent.get_move() # Gets your agent's move
+                       sys.stdout.write(str(x) + " " + str(y) + "\n")
+               elif line.split(" ")[0] == "QUIT":
+                       #sys.stderr.write(sys.argv[0] + " : Quitting\n")
+                       agent.quit(" ".join(line.split(" ")[1:])) # Quits the game
+                       break
+               elif line.split(" ")[0] == "BOARD":
+                       s = ""
+                       line = sys.stdin.readline().strip(" \r\n")
+                       while line != "END BOARD":
+                               s += line + "\n"
+                               line = sys.stdin.readline().strip(" \r\n")
+                       agent.board.reset_board(s)
+                       
+               else:
+                       agent.update(line) # Updates agent.board
+       return 0
+
+
+# Sort of works?
+
+class ExternalWrapper(ExternalAgent):
+       def __init__(self, agent):
+               run = "python -u -c \"import sys;import os;from qchess import *;agent = " + agent.__class__.__name__ + "('" + agent.name + "','"+agent.colour+"');sys.stdin.readline();sys.exit(run_agent(agent))\""
+               # str(run)
+               ExternalAgent.__init__(self, run, agent.colour)
 
+       
 

UCC git Repository :: git.ucc.asn.au