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

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