Did something, apparently
[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 # Player that runs from another process
25 class ExternalAgent(Player):
26
27
28         def __init__(self, name, colour):
29                 Player.__init__(self, name, colour)
30                 self.p = subprocess.Popen(name,bufsize=0,stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True,universal_newlines=True)
31                 
32                 self.send_message(colour)
33
34         def send_message(self, s):
35                 if agent_timeout > 0.0:
36                         ready = select.select([], [self.p.stdin], [], agent_timeout)[1]
37                 else:
38                         ready = [self.p.stdin]
39                 if self.p.stdin in ready:
40                         #sys.stderr.write("Writing \'" + s + "\' to " + str(self.p) + "\n")
41                         try:
42                                 self.p.stdin.write(s + "\n")
43                         except:
44                                 raise Exception("UNRESPONSIVE")
45                 else:
46                         raise Exception("TIMEOUT")
47
48         def get_response(self):
49                 if agent_timeout > 0.0:
50                         ready = select.select([self.p.stdout], [], [], agent_timeout)[0]
51                 else:
52                         ready = [self.p.stdout]
53                 if self.p.stdout in ready:
54                         #sys.stderr.write("Reading from " + str(self.p) + " 's stdout...\n")
55                         try:
56                                 result = self.p.stdout.readline().strip(" \t\r\n")
57                                 #sys.stderr.write("Read \'" + result + "\' from " + str(self.p) + "\n")
58                                 return result
59                         except: # Exception, e:
60                                 raise Exception("UNRESPONSIVE")
61                 else:
62                         raise Exception("TIMEOUT")
63
64         def select(self):
65
66                 self.send_message("SELECTION?")
67                 line = self.get_response()
68                 
69                 try:
70                         m = re.match("\s*(\d+)\s+(\d+)\s*", line)
71                         result = map(int, [m.group(1), m.group(2)])
72                 except:
73                         raise Exception("GIBBERISH \"" + str(line) + "\"")
74                 return result
75
76         def update(self, result):
77                 #print "Update " + str(result) + " called for AgentPlayer"
78                 self.send_message(result)
79                 return result
80
81         def get_move(self):
82                 
83                 self.send_message("MOVE?")
84                 line = self.get_response()
85                 
86                 try:
87                         m = re.match("\s*(\d+)\s+(\d+)\s*", line)
88                         result = map(int, [m.group(1), m.group(2)])
89
90                 except:
91                         raise Exception("GIBBERISH \"" + str(line) + "\"")
92                 return result
93
94         def reset_board(self, s):
95                 self.send_message("BOARD")
96                 for line in s.split("\n"):
97                         self.send_message(line.strip(" \r\n"))
98                 self.send_message("END BOARD")
99
100         def quit(self, final_result):
101                 try:
102                         self.send_message("QUIT " + final_result)
103                 except:
104                         self.p.kill()
105
106 # So you want to be a player here?
107 class HumanPlayer(Player):
108         def __init__(self, name, colour):
109                 Player.__init__(self, name, colour)
110                 
111         # Select your preferred account
112         def select(self):
113                 if isinstance(graphics, GraphicsThread):
114                         # Basically, we let the graphics thread do some shit and then return that information to the game thread
115                         graphics.cond.acquire()
116                         # We wait for the graphics thread to select a piece
117                         while graphics.stopped() == False and graphics.state["select"] == None:
118                                 graphics.cond.wait() # The difference between humans and machines is that humans sleep
119                         select = graphics.state["select"]
120                         
121                         
122                         graphics.cond.release()
123                         if graphics.stopped():
124                                 return [-1,-1]
125                         return [select.x, select.y]
126                 else:
127                         # Since I don't display the board in this case, I'm not sure why I filled it in...
128                         while True:
129                                 sys.stdout.write("SELECTION?\n")
130                                 try:
131                                         p = map(int, sys.stdin.readline().strip("\r\n ").split(" "))
132                                 except:
133                                         sys.stderr.write("ILLEGAL GIBBERISH\n")
134                                         continue
135         # It's your move captain
136         def get_move(self):
137                 if isinstance(graphics, GraphicsThread):
138                         graphics.cond.acquire()
139                         while graphics.stopped() == False and graphics.state["dest"] == None:
140                                 graphics.cond.wait()
141                         graphics.cond.release()
142                         
143                         return graphics.state["dest"]
144                 else:
145
146                         while True:
147                                 sys.stdout.write("MOVE?\n")
148                                 try:
149                                         p = map(int, sys.stdin.readline().strip("\r\n ").split(" "))
150                                 except:
151                                         sys.stderr.write("ILLEGAL GIBBERISH\n")
152                                         continue
153
154         # Are you sure you want to quit?
155         def quit(self, final_result):
156                 if graphics == None:            
157                         sys.stdout.write("QUIT " + final_result + "\n")
158
159         # Completely useless function
160         def update(self, result):
161                 if isinstance(graphics, GraphicsThread):
162                         pass
163                 else:
164                         sys.stdout.write(result + "\n") 
165                 return result
166
167
168 # Default internal player (makes random moves)
169 class InternalAgent(Player):
170         def __init__(self, name, colour):
171                 Player.__init__(self, name, colour)
172                 self.choice = None
173
174                 self.board = Board(style = "agent")
175
176
177
178         def update(self, result):
179                 
180                 self.board.update(result)
181                 #self.board.verify()
182                 return result
183
184         def reset_board(self, s):
185                 self.board.reset_board(s)
186
187         def quit(self, final_result):
188                 pass
189
190 class AgentRandom(InternalAgent):
191         def __init__(self, name, colour):
192                 InternalAgent.__init__(self, name, colour)
193
194         def select(self):
195                 while True:
196                         self.choice = self.board.pieces[self.colour][random.randint(0, len(self.board.pieces[self.colour])-1)]
197                         all_moves = []
198                         # Check that the piece has some possibility to move
199                         tmp = self.choice.current_type
200                         if tmp == "unknown": # For unknown pieces, try both types
201                                 for t in self.choice.types:
202                                         if t == "unknown":
203                                                 continue
204                                         self.choice.current_type = t
205                                         all_moves += self.board.possible_moves(self.choice)
206                         else:
207                                 all_moves = self.board.possible_moves(self.choice)
208                         self.choice.current_type = tmp
209                         if len(all_moves) > 0:
210                                 break
211                 return [self.choice.x, self.choice.y]
212
213         def get_move(self):
214                 moves = self.board.possible_moves(self.choice)
215                 move = moves[random.randint(0, len(moves)-1)]
216                 return move
217
218
219 # Terrible, terrible hacks
220
221 def run_agent(agent):
222         #sys.stderr.write(sys.argv[0] + " : Running agent " + str(agent) + "\n")
223         while True:
224                 line = sys.stdin.readline().strip(" \r\n")
225                 if line == "SELECTION?":
226                         #sys.stderr.write(sys.argv[0] + " : Make selection\n")
227                         [x,y] = agent.select() # Gets your agent's selection
228                         #sys.stderr.write(sys.argv[0] + " : Selection was " + str(agent.choice) + "\n")
229                         sys.stdout.write(str(x) + " " + str(y) + "\n")                          
230                 elif line == "MOVE?":
231                         #sys.stderr.write(sys.argv[0] + " : Make move\n")
232                         [x,y] = agent.get_move() # Gets your agent's move
233                         sys.stdout.write(str(x) + " " + str(y) + "\n")
234                 elif line.split(" ")[0] == "QUIT":
235                         #sys.stderr.write(sys.argv[0] + " : Quitting\n")
236                         agent.quit(" ".join(line.split(" ")[1:])) # Quits the game
237                         break
238                 elif line.split(" ")[0] == "BOARD":
239                         s = ""
240                         line = sys.stdin.readline().strip(" \r\n")
241                         while line != "END BOARD":
242                                 s += line + "\n"
243                                 line = sys.stdin.readline().strip(" \r\n")
244                         agent.board.reset_board(s)
245                         
246                 else:
247                         agent.update(line) # Updates agent.board
248         return 0
249
250
251 # Sort of works?
252
253 class ExternalWrapper(ExternalAgent):
254         def __init__(self, agent):
255                 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))\""
256                 # str(run)
257                 ExternalAgent.__init__(self, run, agent.colour)
258
259         
260

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