6 agent_timeout = -1.0 # Timeout in seconds for AI players to make moves
7 # WARNING: Won't work for windows based operating systems
9 if platform.system() == "Windows":
10 agent_timeout = -1 # Hence this
12 # A player who can't play
14 def __init__(self, name, colour):
18 def update(self, result):
21 def reset_board(self, s):
25 return self.name + "<"+str(self.colour)+">"
27 def base_player(self):
32 def open_fifo(name, mode, timeout=None):
34 return open(name, mode)
37 class Worker(threading.Thread):
39 threading.Thread.__init__(self)
44 self.result = open(name, mode)
51 while time.time() - start < timeout:
52 if w.is_alive() == False:
59 #sys.stderr.write("FIFO_TIMEOUT!\n")
65 #sys.stderr.write("Opened other end!\n")
72 raise Exception("FIFO_TIMEOUT")
78 # Player that runs through a fifo
79 class FifoPlayer(Player):
83 def __init__(self, name, colour):
84 Player.__init__(self, name, colour)
85 os.mkfifo(self.name+".in")
86 os.mkfifo(self.name+".out")
92 def update(self, result):
93 sys.stderr.write("update fifo called\n")
95 self.fifo_out = open_fifo(self.name+".out", "w", FifoPlayer.timeout)
97 raise Exception("FIFO_TIMEOUT")
99 self.fifo_out.write(result +"\n")
100 self.fifo_out.close()
104 sys.stderr.write("select fifo called\n")
106 self.fifo_out = open_fifo(self.name+".out", "w", FifoPlayer.timeout)
108 #sys.stderr.write("TIMEOUT\n")
109 raise Exception("FIFO_TIMEOUT")
112 self.fifo_out.write("SELECT?\n")
113 self.fifo_out.close()
114 self.fifo_in = open_fifo(self.name+".in", "r", FifoPlayer.timeout)
115 s = map(int, self.fifo_in.readline().strip(" \r\n").split(" "))
120 sys.stderr.write("get_move fifo called\n")
122 self.fifo_out = open_fifo(self.name+".out", "w", FifoPlayer.timeout)
124 raise Exception("FIFO_TIMEOUT")
126 self.fifo_out.write("MOVE?\n")
127 self.fifo_out.close()
128 self.fifo_in = open_fifo(self.name+".in", "r", FifoPlayer.timeout)
129 s = map(int, self.fifo_in.readline().strip(" \r\n").split(" "))
133 def quit(self, result):
135 self.fifo_out = open_fifo(self.name+".out", "w", FifoPlayer.timeout)
137 os.remove(self.name+".in")
138 os.remove(self.name+".out")
139 #raise Exception("FIFO_TIMEOUT")
142 self.fifo_out.write(result + "\n")
143 self.fifo_out.close()
144 os.remove(self.name+".in")
145 os.remove(self.name+".out")
147 # Player that runs from another process
148 class ExternalAgent(Player):
151 def __init__(self, name, colour):
152 Player.__init__(self, name, colour)
153 self.p = subprocess.Popen(name,bufsize=0,stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True,universal_newlines=True)
155 self.send_message(colour)
157 def send_message(self, s):
158 if agent_timeout > 0.0:
159 ready = select.select([], [self.p.stdin], [], agent_timeout)[1]
161 ready = [self.p.stdin]
162 if self.p.stdin in ready:
163 #sys.stderr.write("Writing \'" + s + "\' to " + str(self.p) + "\n")
165 self.p.stdin.write(s + "\n")
167 raise Exception("UNRESPONSIVE")
169 raise Exception("TIMEOUT")
171 def get_response(self):
172 if agent_timeout > 0.0:
173 ready = select.select([self.p.stdout], [], [], agent_timeout)[0]
175 ready = [self.p.stdout]
176 if self.p.stdout in ready:
177 #sys.stderr.write("Reading from " + str(self.p) + " 's stdout...\n")
179 result = self.p.stdout.readline().strip(" \t\r\n")
180 #sys.stderr.write("Read \'" + result + "\' from " + str(self.p) + "\n")
182 except: # Exception, e:
183 raise Exception("UNRESPONSIVE")
185 raise Exception("TIMEOUT")
189 self.send_message("SELECTION?")
190 line = self.get_response()
193 m = re.match("\s*(\d+)\s+(\d+)\s*", line)
194 result = map(int, [m.group(1), m.group(2)])
196 raise Exception("GIBBERISH \"" + str(line) + "\"")
199 def update(self, result):
200 #print "Update " + str(result) + " called for AgentPlayer"
201 self.send_message(result)
206 self.send_message("MOVE?")
207 line = self.get_response()
210 m = re.match("\s*(\d+)\s+(\d+)\s*", line)
211 result = map(int, [m.group(1), m.group(2)])
214 raise Exception("GIBBERISH \"" + str(line) + "\"")
217 def reset_board(self, s):
218 self.send_message("BOARD")
219 for line in s.split("\n"):
220 self.send_message(line.strip(" \r\n"))
221 self.send_message("END BOARD")
223 def quit(self, final_result):
225 self.send_message("QUIT " + final_result)
229 # So you want to be a player here?
230 class HumanPlayer(Player):
231 def __init__(self, name, colour):
232 Player.__init__(self, name, colour)
234 # Select your preferred account
236 if isinstance(graphics, GraphicsThread):
237 # Basically, we let the graphics thread do some shit and then return that information to the game thread
238 graphics.cond.acquire()
239 # We wait for the graphics thread to select a piece
240 while graphics.stopped() == False and graphics.state["select"] == None:
241 graphics.cond.wait() # The difference between humans and machines is that humans sleep
242 select = graphics.state["select"]
245 graphics.cond.release()
246 if graphics.stopped():
248 return [select.x, select.y]
250 # Since I don't display the board in this case, I'm not sure why I filled it in...
252 sys.stdout.write("SELECTION?\n")
254 p = map(int, sys.stdin.readline().strip("\r\n ").split(" "))
256 sys.stderr.write("ILLEGAL GIBBERISH\n")
258 # It's your move captain
260 if isinstance(graphics, GraphicsThread):
261 graphics.cond.acquire()
262 while graphics.stopped() == False and graphics.state["dest"] == None:
264 graphics.cond.release()
266 return graphics.state["dest"]
270 sys.stdout.write("MOVE?\n")
272 p = map(int, sys.stdin.readline().strip("\r\n ").split(" "))
274 sys.stderr.write("ILLEGAL GIBBERISH\n")
277 # Are you sure you want to quit?
278 def quit(self, final_result):
280 sys.stdout.write("QUIT " + final_result + "\n")
282 # Completely useless function
283 def update(self, result):
284 if isinstance(graphics, GraphicsThread):
287 sys.stdout.write(result + "\n")
291 # Default internal player (makes random moves)
292 class InternalAgent(Player):
293 def __init__(self, name, colour):
294 Player.__init__(self, name, colour)
297 self.board = Board(style = "agent")
301 def update(self, result):
303 self.board.update(result)
307 def reset_board(self, s):
308 self.board.reset_board(s)
310 def quit(self, final_result):
313 class AgentRandom(InternalAgent):
314 def __init__(self, name, colour):
315 InternalAgent.__init__(self, name, colour)
319 self.choice = self.board.pieces[self.colour][random.randint(0, len(self.board.pieces[self.colour])-1)]
321 # Check that the piece has some possibility to move
322 tmp = self.choice.current_type
323 if tmp == "unknown": # For unknown pieces, try both types
324 for t in self.choice.types:
327 self.choice.current_type = t
328 all_moves += self.board.possible_moves(self.choice)
330 all_moves = self.board.possible_moves(self.choice)
331 self.choice.current_type = tmp
332 if len(all_moves) > 0:
334 return [self.choice.x, self.choice.y]
337 moves = self.board.possible_moves(self.choice)
338 move = moves[random.randint(0, len(moves)-1)]
342 # Terrible, terrible hacks
344 def run_agent(agent):
345 #sys.stderr.write(sys.argv[0] + " : Running agent " + str(agent) + "\n")
347 line = sys.stdin.readline().strip(" \r\n")
348 if line == "SELECTION?":
349 #sys.stderr.write(sys.argv[0] + " : Make selection\n")
350 [x,y] = agent.select() # Gets your agent's selection
351 #sys.stderr.write(sys.argv[0] + " : Selection was " + str(agent.choice) + "\n")
352 sys.stdout.write(str(x) + " " + str(y) + "\n")
353 elif line == "MOVE?":
354 #sys.stderr.write(sys.argv[0] + " : Make move\n")
355 [x,y] = agent.get_move() # Gets your agent's move
356 sys.stdout.write(str(x) + " " + str(y) + "\n")
357 elif line.split(" ")[0] == "QUIT":
358 #sys.stderr.write(sys.argv[0] + " : Quitting\n")
359 agent.quit(" ".join(line.split(" ")[1:])) # Quits the game
361 elif line.split(" ")[0] == "BOARD":
363 line = sys.stdin.readline().strip(" \r\n")
364 while line != "END BOARD":
366 line = sys.stdin.readline().strip(" \r\n")
367 agent.board.reset_board(s)
370 agent.update(line) # Updates agent.board
376 class ExternalWrapper(ExternalAgent):
377 def __init__(self, agent):
378 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))\""
380 ExternalAgent.__init__(self, run, agent.colour)