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 self.board.push_move(piece, x, y)
54 defenders = self.board.coverage(x, y, piece.colour, reject_allied = False)
56 for d in defenders.keys():
57 d_prob += defenders[d]
58 if len(defenders.keys()) > 0:
59 d_prob /= float(len(defenders.keys()))
64 # Get total probability that the move is threatened
65 attackers = self.board.coverage(x, y, opponent(piece.colour), reject_allied = False)
67 for a in attackers.keys():
68 a_prob += attackers[a]
69 if len(attackers.keys()) > 0:
70 a_prob /= float(len(attackers.keys()))
80 value = self.aggression * (1.0 + d_prob) * self.get_value(target) - self.defence * (1.0 - d_prob) * a_prob * self.get_value(piece)
82 # Adjust score based on movement of piece out of danger
83 attackers = self.board.coverage(piece.x, piece.y, opponent(piece.colour))
85 for a in attackers.keys():
86 s_prob += attackers[a]
87 if len(attackers.keys()) > 0:
88 s_prob /= float(len(attackers.keys()))
92 value += self.defence * s_prob * self.get_value(piece)
94 # Adjust score based on probability that the move is actually possible
95 moves.append([[x, y], grid[x][y] * value])
97 moves.sort(key = lambda e : e[1], reverse = True)
98 #sys.stderr.write(sys.argv[0] + ": Moves for " + str(piece) + " are " + str(moves) + "\n")
100 piece.last_moves = moves
101 piece.selected_moves = None
108 def select_best(self, colour):
112 for p in self.board.pieces[colour]:
113 self.choice = p # Temporarily pick that piece
114 m = self.prioritise_moves(p)
116 all_moves.update({p : m[0]})
118 if len(all_moves.items()) <= 0:
122 opts = all_moves.items()
123 opts.sort(key = lambda e : e[1][1], reverse = True)
125 if self.depth >= self.max_depth:
129 if self.recurse_for >= 0:
130 opts = opts[0:self.recurse_for]
131 #sys.stderr.write(sys.argv[0] + " : Before recurse, options are " + str(opts) + "\n")
133 # Take the best few moves, and recurse
134 for choice in opts[0:self.recurse_for]:
135 [xx,yy] = [choice[0].x, choice[0].y] # Remember position
136 [nx,ny] = choice[1][0] # Target
137 [choice[0].x, choice[0].y] = [nx, ny] # Set position
138 target = self.board.grid[nx][ny] # Remember piece in spot
139 self.board.grid[xx][yy] = None # Remove piece
140 self.board.grid[nx][ny] = choice[0] # Replace with moving piece
143 best_enemy_move = self.select_best(opponent(choice[0].colour))
144 choice[1][1] -= best_enemy_move[1][1] / float(self.depth + 1.0)
146 [choice[0].x, choice[0].y] = [xx, yy] # Restore position
147 self.board.grid[nx][ny] = target # Restore taken piece
148 self.board.grid[xx][yy] = choice[0] # Restore moved piece
152 opts.sort(key = lambda e : e[1][1], reverse = True)
153 #sys.stderr.write(sys.argv[0] + " : After recurse, options are " + str(opts) + "\n")
160 # Returns [x,y] of selected piece
162 #sys.stderr.write("Getting choice...")
163 self.choice = self.select_best(self.colour)[0]
165 #sys.stderr.write(" Done " + str(self.choice)+"\n")
166 return [self.choice.x, self.choice.y]
168 # Returns [x,y] of square to move selected piece into
170 #sys.stderr.write("Choice is " + str(self.choice) + "\n")
171 self.choice.selected_moves = self.choice.last_moves
172 moves = self.prioritise_moves(self.choice)
176 return AgentRandom.get_move(self)