4 class AgentBishop(AgentRandom): # Inherits from AgentRandom (in qchess)
5 def __init__(self, name, colour):
6 InternalAgent.__init__(self, name, colour)
7 self.value = {"pawn" : 1, "bishop" : 3, "knight" : 3, "rook" : 5, "queen" : 9, "king" : 100, "unknown" : 4}
9 self.aggression = 2.0 # Multiplier for scoring due to aggressive actions
10 self.defence = 1.0 # Multiplier for scoring due to defensive actions
12 self.depth = 0 # Current depth
13 self.max_depth = 2 # Recurse this many times (for some reason, makes more mistakes when this is increased???)
14 self.recurse_for = -1 # Recurse for the best few moves each times (less than 0 = all moves)
16 for p in self.board.pieces["white"] + self.board.pieces["black"]:
18 p.selected_moves = None
22 def get_value(self, piece):
25 return float(self.value[piece.types[0]] + self.value[piece.types[1]]) / 2.0
27 # Score possible moves for the piece
29 def prioritise_moves(self, piece):
31 #sys.stderr.write(sys.argv[0] + " : " + str(self) + " prioritise called for " + str(piece) + "\n")
35 grid = self.board.probability_grid(piece)
36 #sys.stderr.write("\t Probability grid " + str(grid) + "\n")
40 if grid[x][y] < 0.3: # Throw out moves with < 30% probability
41 #sys.stderr.write("\tReject " + str(x) + "," + str(y) + " (" + str(grid[x][y]) + ")\n")
44 target = self.board.grid[x][y]
49 # Get total probability that the move is protected
50 [xx,yy] = [piece.x, piece.y]
51 [piece.x, piece.y] = [x, y]
52 self.board.grid[x][y] = piece
53 self.board.grid[xx][yy] = None
55 defenders = self.board.coverage(x, y, piece.colour, reject_allied = False)
57 for d in defenders.keys():
58 d_prob += defenders[d]
59 if len(defenders.keys()) > 0:
60 d_prob /= float(len(defenders.keys()))
65 # Get total probability that the move is threatened
66 attackers = self.board.coverage(x, y, opponent(piece.colour), reject_allied = False)
68 for a in attackers.keys():
69 a_prob += attackers[a]
70 if len(attackers.keys()) > 0:
71 a_prob /= float(len(attackers.keys()))
76 self.board.grid[x][y] = target
77 self.board.grid[xx][yy] = piece
78 [piece.x, piece.y] = [xx, yy]
82 value = self.aggression * (1.0 + d_prob) * self.get_value(target) - self.defence * (1.0 - d_prob) * a_prob * self.get_value(piece)
84 # Adjust score based on movement of piece out of danger
85 attackers = self.board.coverage(piece.x, piece.y, opponent(piece.colour))
87 for a in attackers.keys():
88 s_prob += attackers[a]
89 if len(attackers.keys()) > 0:
90 s_prob /= float(len(attackers.keys()))
94 value += self.defence * s_prob * self.get_value(piece)
96 # Adjust score based on probability that the move is actually possible
97 moves.append([[x, y], grid[x][y] * value])
99 moves.sort(key = lambda e : e[1], reverse = True)
100 #sys.stderr.write(sys.argv[0] + ": Moves for " + str(piece) + " are " + str(moves) + "\n")
102 piece.last_moves = moves
103 piece.selected_moves = None
110 def select_best(self, colour):
114 for p in self.board.pieces[colour]:
115 self.choice = p # Temporarily pick that piece
116 m = self.prioritise_moves(p)
118 all_moves.update({p : m[0]})
120 if len(all_moves.items()) <= 0:
124 opts = all_moves.items()
125 opts.sort(key = lambda e : e[1][1], reverse = True)
127 if self.depth >= self.max_depth:
131 if self.recurse_for >= 0:
132 opts = opts[0:self.recurse_for]
133 #sys.stderr.write(sys.argv[0] + " : Before recurse, options are " + str(opts) + "\n")
135 # Take the best few moves, and recurse
136 for choice in opts[0:self.recurse_for]:
137 [xx,yy] = [choice[0].x, choice[0].y] # Remember position
138 [nx,ny] = choice[1][0] # Target
139 [choice[0].x, choice[0].y] = [nx, ny] # Set position
140 target = self.board.grid[nx][ny] # Remember piece in spot
141 self.board.grid[xx][yy] = None # Remove piece
142 self.board.grid[nx][ny] = choice[0] # Replace with moving piece
145 best_enemy_move = self.select_best(opponent(choice[0].colour))
146 choice[1][1] -= best_enemy_move[1][1] / float(self.depth + 1.0)
148 [choice[0].x, choice[0].y] = [xx, yy] # Restore position
149 self.board.grid[nx][ny] = target # Restore taken piece
150 self.board.grid[xx][yy] = choice[0] # Restore moved piece
154 opts.sort(key = lambda e : e[1][1], reverse = True)
155 #sys.stderr.write(sys.argv[0] + " : After recurse, options are " + str(opts) + "\n")
162 # Returns [x,y] of selected piece
164 #sys.stderr.write("Getting choice...")
165 self.choice = self.select_best(self.colour)[0]
167 #sys.stderr.write(" Done " + str(self.choice)+"\n")
168 return [self.choice.x, self.choice.y]
170 # Returns [x,y] of square to move selected piece into
172 #sys.stderr.write("Choice is " + str(self.choice) + "\n")
173 self.choice.selected_moves = self.choice.last_moves
174 moves = self.prioritise_moves(self.choice)
178 return AgentRandom.get_move(self)