Work on cgi bin stuff
[progcomp2013.git] / qchess / src / player.py
1 import subprocess
2 import select
3 import platform
4 import re
5
6 agent_timeout = -1.0 # Timeout in seconds for AI players to make moves
7                         # WARNING: Won't work for windows based operating systems
8
9 if platform.system() == "Windows":
10         agent_timeout = -1 # Hence this
11
12 # A player who can't play
13 class Player():
14         def __init__(self, name, colour):
15                 self.name = name
16                 self.colour = colour
17
18         def update(self, result):
19                 return result
20
21         def reset_board(self, s):
22                 pass
23         
24         def __str__(self):
25                 return self.name + "<"+str(self.colour)+">"
26
27         def base_player(self):
28                 return self
29
30 # Player that runs through a fifo
31 class FifoPlayer(Player):
32         def __init__(self, name, colour):
33                 Player.__init__(self, name, colour)
34                 os.mkfifo(self.name+".in")
35                 os.mkfifo(self.name+".out")
36                 
37                 
38                 
39                 
40                 
41         def update(self, result):
42                 sys.stderr.write("update fifo called\n")
43                 self.fifo_out = open(self.name+".out", "w")
44                 self.fifo_out.write(result +"\n")
45                 self.fifo_out.close()
46                 return result
47                 
48         def select(self):
49                 sys.stderr.write("select fifo called\n")
50                 self.fifo_out = open(self.name+".out", "w")
51                 self.fifo_out.write("SELECT?\n")
52                 self.fifo_out.close()
53                 self.fifo_in = open(self.name+".in", "r")
54                 s = map(int, self.fifo_in.readline().strip(" \r\n").split(" "))
55                 self.fifo_in.close()
56                 return s
57         
58         def get_move(self):
59                 sys.stderr.write("get_move fifo called\n")
60                 self.fifo_out = open(self.name+".out", "w")
61                 self.fifo_out.write("MOVE?\n")
62                 self.fifo_out.close()
63                 self.fifo_in = open(self.name+".in", "r")
64                 s = map(int, self.fifo_in.readline().strip(" \r\n").split(" "))
65                 self.fifo_in.close()
66                 return s
67         
68         def quit(self, result):
69                 self.fifo_out = open(self.name+".out", "w")
70                 self.fifo_out.write(result + "\n")
71                 self.fifo_out.close()
72                 os.remove(self.name+".in")
73                 os.remove(self.name+".out")
74
75 # Player that runs from another process
76 class ExternalAgent(Player):
77
78
79         def __init__(self, name, colour):
80                 Player.__init__(self, name, colour)
81                 self.p = subprocess.Popen(name,bufsize=0,stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True,universal_newlines=True)
82                 
83                 self.send_message(colour)
84
85         def send_message(self, s):
86                 if agent_timeout > 0.0:
87                         ready = select.select([], [self.p.stdin], [], agent_timeout)[1]
88                 else:
89                         ready = [self.p.stdin]
90                 if self.p.stdin in ready:
91                         #sys.stderr.write("Writing \'" + s + "\' to " + str(self.p) + "\n")
92                         try:
93                                 self.p.stdin.write(s + "\n")
94                         except:
95                                 raise Exception("UNRESPONSIVE")
96                 else:
97                         raise Exception("TIMEOUT")
98
99         def get_response(self):
100                 if agent_timeout > 0.0:
101                         ready = select.select([self.p.stdout], [], [], agent_timeout)[0]
102                 else:
103                         ready = [self.p.stdout]
104                 if self.p.stdout in ready:
105                         #sys.stderr.write("Reading from " + str(self.p) + " 's stdout...\n")
106                         try:
107                                 result = self.p.stdout.readline().strip(" \t\r\n")
108                                 #sys.stderr.write("Read \'" + result + "\' from " + str(self.p) + "\n")
109                                 return result
110                         except: # Exception, e:
111                                 raise Exception("UNRESPONSIVE")
112                 else:
113                         raise Exception("TIMEOUT")
114
115         def select(self):
116
117                 self.send_message("SELECTION?")
118                 line = self.get_response()
119                 
120                 try:
121                         m = re.match("\s*(\d+)\s+(\d+)\s*", line)
122                         result = map(int, [m.group(1), m.group(2)])
123                 except:
124                         raise Exception("GIBBERISH \"" + str(line) + "\"")
125                 return result
126
127         def update(self, result):
128                 #print "Update " + str(result) + " called for AgentPlayer"
129                 self.send_message(result)
130                 return result
131
132         def get_move(self):
133                 
134                 self.send_message("MOVE?")
135                 line = self.get_response()
136                 
137                 try:
138                         m = re.match("\s*(\d+)\s+(\d+)\s*", line)
139                         result = map(int, [m.group(1), m.group(2)])
140
141                 except:
142                         raise Exception("GIBBERISH \"" + str(line) + "\"")
143                 return result
144
145         def reset_board(self, s):
146                 self.send_message("BOARD")
147                 for line in s.split("\n"):
148                         self.send_message(line.strip(" \r\n"))
149                 self.send_message("END BOARD")
150
151         def quit(self, final_result):
152                 try:
153                         self.send_message("QUIT " + final_result)
154                 except:
155                         self.p.kill()
156
157 # So you want to be a player here?
158 class HumanPlayer(Player):
159         def __init__(self, name, colour):
160                 Player.__init__(self, name, colour)
161                 
162         # Select your preferred account
163         def select(self):
164                 if isinstance(graphics, GraphicsThread):
165                         # Basically, we let the graphics thread do some shit and then return that information to the game thread
166                         graphics.cond.acquire()
167                         # We wait for the graphics thread to select a piece
168                         while graphics.stopped() == False and graphics.state["select"] == None:
169                                 graphics.cond.wait() # The difference between humans and machines is that humans sleep
170                         select = graphics.state["select"]
171                         
172                         
173                         graphics.cond.release()
174                         if graphics.stopped():
175                                 return [-1,-1]
176                         return [select.x, select.y]
177                 else:
178                         # Since I don't display the board in this case, I'm not sure why I filled it in...
179                         while True:
180                                 sys.stdout.write("SELECTION?\n")
181                                 try:
182                                         p = map(int, sys.stdin.readline().strip("\r\n ").split(" "))
183                                 except:
184                                         sys.stderr.write("ILLEGAL GIBBERISH\n")
185                                         continue
186         # It's your move captain
187         def get_move(self):
188                 if isinstance(graphics, GraphicsThread):
189                         graphics.cond.acquire()
190                         while graphics.stopped() == False and graphics.state["dest"] == None:
191                                 graphics.cond.wait()
192                         graphics.cond.release()
193                         
194                         return graphics.state["dest"]
195                 else:
196
197                         while True:
198                                 sys.stdout.write("MOVE?\n")
199                                 try:
200                                         p = map(int, sys.stdin.readline().strip("\r\n ").split(" "))
201                                 except:
202                                         sys.stderr.write("ILLEGAL GIBBERISH\n")
203                                         continue
204
205         # Are you sure you want to quit?
206         def quit(self, final_result):
207                 if graphics == None:            
208                         sys.stdout.write("QUIT " + final_result + "\n")
209
210         # Completely useless function
211         def update(self, result):
212                 if isinstance(graphics, GraphicsThread):
213                         pass
214                 else:
215                         sys.stdout.write(result + "\n") 
216                 return result
217
218
219 # Default internal player (makes random moves)
220 class InternalAgent(Player):
221         def __init__(self, name, colour):
222                 Player.__init__(self, name, colour)
223                 self.choice = None
224
225                 self.board = Board(style = "agent")
226
227
228
229         def update(self, result):
230                 
231                 self.board.update(result)
232                 #self.board.verify()
233                 return result
234
235         def reset_board(self, s):
236                 self.board.reset_board(s)
237
238         def quit(self, final_result):
239                 pass
240
241 class AgentRandom(InternalAgent):
242         def __init__(self, name, colour):
243                 InternalAgent.__init__(self, name, colour)
244
245         def select(self):
246                 while True:
247                         self.choice = self.board.pieces[self.colour][random.randint(0, len(self.board.pieces[self.colour])-1)]
248                         all_moves = []
249                         # Check that the piece has some possibility to move
250                         tmp = self.choice.current_type
251                         if tmp == "unknown": # For unknown pieces, try both types
252                                 for t in self.choice.types:
253                                         if t == "unknown":
254                                                 continue
255                                         self.choice.current_type = t
256                                         all_moves += self.board.possible_moves(self.choice)
257                         else:
258                                 all_moves = self.board.possible_moves(self.choice)
259                         self.choice.current_type = tmp
260                         if len(all_moves) > 0:
261                                 break
262                 return [self.choice.x, self.choice.y]
263
264         def get_move(self):
265                 moves = self.board.possible_moves(self.choice)
266                 move = moves[random.randint(0, len(moves)-1)]
267                 return move
268
269
270 # Terrible, terrible hacks
271
272 def run_agent(agent):
273         #sys.stderr.write(sys.argv[0] + " : Running agent " + str(agent) + "\n")
274         while True:
275                 line = sys.stdin.readline().strip(" \r\n")
276                 if line == "SELECTION?":
277                         #sys.stderr.write(sys.argv[0] + " : Make selection\n")
278                         [x,y] = agent.select() # Gets your agent's selection
279                         #sys.stderr.write(sys.argv[0] + " : Selection was " + str(agent.choice) + "\n")
280                         sys.stdout.write(str(x) + " " + str(y) + "\n")                          
281                 elif line == "MOVE?":
282                         #sys.stderr.write(sys.argv[0] + " : Make move\n")
283                         [x,y] = agent.get_move() # Gets your agent's move
284                         sys.stdout.write(str(x) + " " + str(y) + "\n")
285                 elif line.split(" ")[0] == "QUIT":
286                         #sys.stderr.write(sys.argv[0] + " : Quitting\n")
287                         agent.quit(" ".join(line.split(" ")[1:])) # Quits the game
288                         break
289                 elif line.split(" ")[0] == "BOARD":
290                         s = ""
291                         line = sys.stdin.readline().strip(" \r\n")
292                         while line != "END BOARD":
293                                 s += line + "\n"
294                                 line = sys.stdin.readline().strip(" \r\n")
295                         agent.board.reset_board(s)
296                         
297                 else:
298                         agent.update(line) # Updates agent.board
299         return 0
300
301
302 # Sort of works?
303
304 class ExternalWrapper(ExternalAgent):
305         def __init__(self, agent):
306                 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))\""
307                 # str(run)
308                 ExternalAgent.__init__(self, run, agent.colour)
309
310         
311

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