X-Git-Url: https://git.ucc.asn.au/?p=progcomp2013.git;a=blobdiff_plain;f=agents%2Fbishop.py;h=ea96c2ce5e745e35030ea68f15e6d7a52d8d1516;hp=3c7738e540bc9d17f2496d6ff6e137089e07998a;hb=0325af7e6f9c20b549efa84754b4a4a206fe66cc;hpb=444244d5c7698bb7861cdb7c0ec6bfb0e8cebfb7 diff --git a/agents/bishop.py b/agents/bishop.py index 3c7738e..ea96c2c 100755 --- a/agents/bishop.py +++ b/agents/bishop.py @@ -3,192 +3,15 @@ from qchess import * """ - Agent Bishop - ( an agent, not an implementation of a bishop chess piece!) -""" - - - - -# Skeleton class for your agent -class Agent(AgentRandom): # Inherits from AgentRandom (in qchess.py) - def __init__(self, name, colour): - AgentRandom.__init__(self, name, colour) - self.value = {"pawn" : 1, "bishop" : 3, "knight" : 3, "rook" : 5, "queen" : 9, "king" : 100, "unknown" : 4} - - self.aggression = 2.0 # Multiplier for scoring due to aggressive actions - self.defence = 1.0 # Multiplier for scoring due to defensive actions - - self.depth = 0 # Current depth - self.max_depth = 2 # Recurse this many times (for some reason, makes more mistakes when this is increased???) - self.recurse_for = -1 # Recurse for the best few moves each times (less than 0 = all moves) - - for p in self.board.pieces["white"] + self.board.pieces["black"]: - p.last_moves = None - p.selected_moves = None - - - - def get_value(self, piece): - if piece == None: - return 0.0 - return float(self.value[piece.types[0]] + self.value[piece.types[1]]) / 2.0 - - # Score possible moves for the piece - - def prioritise_moves(self, piece): - - #sys.stderr.write(sys.argv[0] + ": prioritise called for " + str(piece) + "\n") - - - - grid = self.board.probability_grid(piece) - #sys.stderr.write("\t Probability grid " + str(grid) + "\n") - moves = [] - for x in range(w): - for y in range(h): - if grid[x][y] < 0.3: # Throw out moves with < 30% probability - #sys.stderr.write("\tReject " + str(x) + "," + str(y) + " (" + str(grid[x][y]) + ")\n") - continue - - target = self.board.grid[x][y] - - - - - # Get total probability that the move is protected - [xx,yy] = [piece.x, piece.y] - [piece.x, piece.y] = [x, y] - self.board.grid[x][y] = piece - self.board.grid[xx][yy] = None - - defenders = self.board.coverage(x, y, piece.colour, reject_allied = False) - d_prob = 0.0 - for d in defenders.keys(): - d_prob += defenders[d] - if len(defenders.keys()) > 0: - d_prob /= float(len(defenders.keys())) - - if (d_prob > 1.0): - d_prob = 1.0 - - # Get total probability that the move is threatened - attackers = self.board.coverage(x, y, opponent(piece.colour), reject_allied = False) - a_prob = 0.0 - for a in attackers.keys(): - a_prob += attackers[a] - if len(attackers.keys()) > 0: - a_prob /= float(len(attackers.keys())) - - if (a_prob > 1.0): - a_prob = 1.0 - - self.board.grid[x][y] = target - self.board.grid[xx][yy] = piece - [piece.x, piece.y] = [xx, yy] - - - # Score of the move - value = self.aggression * (1.0 + d_prob) * self.get_value(target) - self.defence * (1.0 - d_prob) * a_prob * self.get_value(piece) - - # Adjust score based on movement of piece out of danger - attackers = self.board.coverage(piece.x, piece.y, opponent(piece.colour)) - s_prob = 0.0 - for a in attackers.keys(): - s_prob += attackers[a] - if len(attackers.keys()) > 0: - s_prob /= float(len(attackers.keys())) - - if (s_prob > 1.0): - s_prob = 1.0 - value += self.defence * s_prob * self.get_value(piece) - - # Adjust score based on probability that the move is actually possible - moves.append([[x, y], grid[x][y] * value]) - - moves.sort(key = lambda e : e[1], reverse = True) - #sys.stderr.write(sys.argv[0] + ": Moves for " + str(piece) + " are " + str(moves) + "\n") - - piece.last_moves = moves - piece.selected_moves = None - - - - - return moves - - def select_best(self, colour): - - self.depth += 1 - all_moves = {} - for p in self.board.pieces[colour]: - self.choice = p # Temporarily pick that piece - m = self.prioritise_moves(p) - if len(m) > 0: - all_moves.update({p : m[0]}) - - if len(all_moves.items()) <= 0: - return None - - - opts = all_moves.items() - opts.sort(key = lambda e : e[1][1], reverse = True) - - if self.depth >= self.max_depth: - self.depth -= 1 - return list(opts[0]) - - if self.recurse_for >= 0: - opts = opts[0:self.recurse_for] - #sys.stderr.write(sys.argv[0] + " : Before recurse, options are " + str(opts) + "\n") + This is a wrapper to AgentBishop, which can now be found directly in qchess as one of the internal agents + As well as wrapping, it will also show AgentBishop's thought processes in graphics, which is kind of cool - # Take the best few moves, and recurse - for choice in opts[0:self.recurse_for]: - [xx,yy] = [choice[0].x, choice[0].y] # Remember position - [nx,ny] = choice[1][0] # Target - [choice[0].x, choice[0].y] = [nx, ny] # Set position - target = self.board.grid[nx][ny] # Remember piece in spot - self.board.grid[xx][yy] = None # Remove piece - self.board.grid[nx][ny] = choice[0] # Replace with moving piece - - # Recurse - best_enemy_move = self.select_best(opponent(choice[0].colour)) - choice[1][1] -= best_enemy_move[1][1] / float(self.depth + 1.0) - - [choice[0].x, choice[0].y] = [xx, yy] # Restore position - self.board.grid[nx][ny] = target # Restore taken piece - self.board.grid[xx][yy] = choice[0] # Restore moved piece - - - - opts.sort(key = lambda e : e[1][1], reverse = True) - #sys.stderr.write(sys.argv[0] + " : After recurse, options are " + str(opts) + "\n") - - self.depth -= 1 - return list(opts[0]) - - + So basically, using `./qchess.py @internal:AgentBishop` is better, unless you want to see the graphics +""" - # Returns [x,y] of selected piece - def select(self): - - self.choice = self.select_best(self.colour)[0] - return [self.choice.x, self.choice.y] - # Returns [x,y] of square to move selected piece into - def get_move(self): - self.choice.selected_moves = self.choice.last_moves - moves = self.prioritise_moves(self.choice) - if len(moves) > 0: - return moves[0][0] - else: - return AgentRandom.get_move(self) - - - - # Horrible messy graphics class that draws what the agent is doing, kind of useful for testing -class AgentGraphics(GraphicsThread): +class AgentBishop_Graphics(GraphicsThread): def __init__(self, board, title): GraphicsThread.__init__(self, board, title, grid_sz = [64,64]) self.choice = None @@ -280,42 +103,13 @@ class AgentGraphics(GraphicsThread): self.moves = None pygame.display.quit() - - -# Main function; don't alter -def main(argv): - - global agent - colour = sys.stdin.readline().strip("\n") # Gets the colour of the agent from stdin - - agent = Agent(argv[0], colour) # Creates your agent - - #graphics = AgentGraphics(agent.board, title="Agent Bishop (" + str(colour) + ") - DEBUG VIEW") - #graphics.start() - - # Plays quantum chess using your agent - while True: - line = sys.stdin.readline().strip(" \r\n") - #sys.stderr.write(argv[0] + ": gets line \"" + str(line) + "\"\n") - if line == "SELECTION?": - [x,y] = agent.select() # Gets your agent's selection - #print "Select " + str(x) + "," + str(y) - sys.stdout.write(str(x) + " " + str(y) + "\n") - elif line == "MOVE?": - [x,y] = agent.get_move() # Gets your agent's move - sys.stdout.write(str(x) + " " + str(y) + "\n") - elif line.split(" ")[0] == "QUIT": - agent.quit(" ".join(line.split(" ")[1:])) # Quits the game -# graphics.stop() - break - else: - agent.update(line) # Updates agent.board - - #graphics.stop() - #graphics.join() - return 0 - -# Don't touch this if __name__ == "__main__": - sys.exit(main(sys.argv)) + + colour = sys.stdin.readline().strip("\r\n") + agent = AgentBishop(sys.argv[0], colour) + graphics = AgentBishop_Graphics(agent.board, "Agent Bishop ("+agent.colour+") DEBUG") + graphics.start() + run_agent(agent) + graphics.stop() + graphics.join()