Progress?
[progcomp2013.git] / qchess / src / agent_bishop.py
1 # A sample agent
2
3
4 class AgentBishop(InternalAgent): # Inherits from InternalAgent (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}
8
9                 self.aggression = 2.0 # Multiplier for scoring due to aggressive actions
10                 self.defence = 1.0 # Multiplier for scoring due to defensive actions
11                 
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)
15
16                 for p in self.board.pieces["white"] + self.board.pieces["black"]:
17                         p.last_moves = None
18                         p.selected_moves = None
19
20                 
21
22         def get_value(self, piece):
23                 if piece == None:
24                         return 0.0
25                 return float(self.value[piece.types[0]] + self.value[piece.types[1]]) / 2.0
26                 
27         # Score possible moves for the piece
28         
29         def prioritise_moves(self, piece):
30
31                 #sys.stderr.write(sys.argv[0] + " : " + str(self) + " prioritise called for " + str(piece) + "\n")
32
33                 
34                 
35                 grid = self.board.probability_grid(piece)
36                 #sys.stderr.write("\t Probability grid " + str(grid) + "\n")
37                 moves = []
38                 for x in range(w):
39                         for y in range(h):
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")
42                                         continue
43
44                                 target = self.board.grid[x][y]
45                         
46                                 
47                                 
48                                 
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
54                                 
55                                 defenders = self.board.coverage(x, y, piece.colour, reject_allied = False)
56                                 d_prob = 0.0
57                                 for d in defenders.keys():
58                                         d_prob += defenders[d]
59                                 if len(defenders.keys()) > 0:
60                                         d_prob /= float(len(defenders.keys()))
61
62                                 if (d_prob > 1.0):
63                                         d_prob = 1.0
64
65                                 # Get total probability that the move is threatened
66                                 attackers = self.board.coverage(x, y, opponent(piece.colour), reject_allied = False)
67                                 a_prob = 0.0
68                                 for a in attackers.keys():
69                                         a_prob += attackers[a]
70                                 if len(attackers.keys()) > 0:
71                                         a_prob /= float(len(attackers.keys()))
72
73                                 if (a_prob > 1.0):
74                                         a_prob = 1.0
75
76                                 self.board.grid[x][y] = target
77                                 self.board.grid[xx][yy] = piece
78                                 [piece.x, piece.y] = [xx, yy]
79
80                                 
81                                 # Score of the move
82                                 value = self.aggression * (1.0 + d_prob) * self.get_value(target) - self.defence * (1.0 - d_prob) * a_prob * self.get_value(piece)
83
84                                 # Adjust score based on movement of piece out of danger
85                                 attackers = self.board.coverage(piece.x, piece.y, opponent(piece.colour))
86                                 s_prob = 0.0
87                                 for a in attackers.keys():
88                                         s_prob += attackers[a]
89                                 if len(attackers.keys()) > 0:
90                                         s_prob /= float(len(attackers.keys()))
91
92                                 if (s_prob > 1.0):
93                                         s_prob = 1.0
94                                 value += self.defence * s_prob * self.get_value(piece)
95                                 
96                                 # Adjust score based on probability that the move is actually possible
97                                 moves.append([[x, y], grid[x][y] * value])
98
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")
101
102                 piece.last_moves = moves
103                 piece.selected_moves = None
104
105                 
106
107                 
108                 return moves
109
110         def select_best(self, colour):
111
112                 self.depth += 1
113                 all_moves = {}
114                 for p in self.board.pieces[colour]:
115                         self.choice = p # Temporarily pick that piece
116                         m = self.prioritise_moves(p)
117                         if len(m) > 0:
118                                 all_moves.update({p : m[0]})
119
120                 if len(all_moves.items()) <= 0:
121                         return None
122                 
123                 
124                 opts = all_moves.items()
125                 opts.sort(key = lambda e : e[1][1], reverse = True)
126
127                 if self.depth >= self.max_depth:
128                         self.depth -= 1
129                         return list(opts[0])
130
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")
134
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
143                         
144                         # Recurse
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)
147                         
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
151                         
152                 
153
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")
156
157                 self.depth -= 1
158                 return list(opts[0])
159
160                 
161
162         # Returns [x,y] of selected piece
163         def select(self):
164                 #sys.stderr.write("Getting choice...")
165                 self.choice = self.select_best(self.colour)[0]
166                 #sys.stderr.write(" Done " + str(self.choice)+"\n")
167                 return [self.choice.x, self.choice.y]
168         
169         # Returns [x,y] of square to move selected piece into
170         def get_move(self):
171                 #sys.stderr.write("Choice is " + str(self.choice) + "\n")
172                 self.choice.selected_moves = self.choice.last_moves
173                 moves = self.prioritise_moves(self.choice)
174                 if len(moves) > 0:
175                         return moves[0][0]
176                 else:
177                         return InternalAgent.get_move(self)
178

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