X-Git-Url: https://git.ucc.asn.au/?p=progcomp2013.git;a=blobdiff_plain;f=qchess%2Fsrc%2Fboard.py;h=5f75d399d6bbdb0d59b9cc57000bb9df1e777054;hp=5dbf1dd2a9486f64a8636815b999ccb89fd0c357;hb=5287b4f869be70ddae4b59a44c448be33f95ccda;hpb=a35e4dc5f4fb6325785b6f8b123266976107b748 diff --git a/qchess/src/board.py b/qchess/src/board.py index 5dbf1dd..5f75d39 100644 --- a/qchess/src/board.py +++ b/qchess/src/board.py @@ -13,6 +13,9 @@ class Board(): self.grid = [[None] * w for _ in range(h)] # 2D List (you can get arrays in python, somehow, but they scare me) self.unrevealed_types = {"white" : piece_types.copy(), "black" : piece_types.copy()} self.king = {"white" : None, "black" : None} # We need to keep track of the king, because he is important + self.max_moves = None + self.moves = 0 + self.move_stack = [] for c in ["black", "white"]: del self.unrevealed_types[c]["unknown"] @@ -30,7 +33,6 @@ class Board(): c.append(Piece(s, 1, y, ["knight"])) c.append(Piece(s, 2, y, ["bishop"])) k = Piece(s, 3, y, ["king", "king"]) # There can only be one ruler! - k.types_revealed[1] = True k.current_type = "king" self.king[s] = k c.append(k) @@ -68,11 +70,10 @@ class Board(): types_left[choice] -= 1 if types_left[choice] <= 0: del types_left[choice] - piece.types.append(choice) + piece.types.append('?' + choice) elif style == "classical": piece.types.append(piece.types[0]) piece.current_type = piece.types[0] - piece.types_revealed[1] = True piece.choice = 0 def clone(self): @@ -82,6 +83,40 @@ class Board(): for i in range(len(mypieces)): newpieces[i].init_from_copy(mypieces[i]) + + # Reset the board from a string + def reset_board(self, s): + self.pieces = {"white" : [], "black" : []} + self.king = {"white" : None, "black" : None} + self.grid = [[None] * w for _ in range(h)] + for x in range(w): + for y in range(h): + self.grid[x][y] = None + + for line in s.split("\n"): + if line == "": + continue + if line[0] == "#": + continue + + tokens = line.split(" ") + [x, y] = map(int, tokens[len(tokens)-1].split(",")) + current_type = tokens[1] + types = map(lambda e : e.strip(" '[],"), line.split('[')[1].split(']')[0].split(',')) + + target = Piece(tokens[0], x, y, types) + target.current_type = current_type + + try: + target.choice = types.index(current_type) + except: + target.choice = -1 + + self.pieces[tokens[0]].append(target) + if target.current_type == "king": + self.king[tokens[0]] = target + + self.grid[x][y] = target def display_grid(self, window = None, grid_sz = [80,80]): @@ -147,15 +182,23 @@ class Board(): del self.unrevealed_types[piece.colour][state] piece.types[type_index] = state - piece.types_revealed[type_index] = True piece.current_type = state if len(self.possible_moves(piece)) <= 0: piece.deselect() # Piece can't move; deselect it + + # Piece needs to recalculate moves + piece.possible_moves = None # Update the board when a piece has been moved def update_move(self, x, y, x2, y2): + piece = self.grid[x][y] + #print "Moving " + str(x) + "," + str(y) + " to " + str(x2) + "," + str(y2) + "; possible_moves are " + str(self.possible_moves(piece)) + + if not [x2,y2] in self.possible_moves(piece): + raise Exception("ILLEGAL move " + str(x2)+","+str(y2)) + self.grid[x][y] = None taken = self.grid[x2][y2] if taken != None: @@ -178,7 +221,13 @@ class Board(): piece.current_type = "queen" piece.deselect() # Uncollapse (?) the wavefunction! - self.verify() + self.moves += 1 + + # All other pieces need to recalculate moves + for p in self.pieces["white"] + self.pieces["black"]: + p.possible_moves = None + + #self.verify() # Update the board from a string # Guesses what to do based on the format of the string @@ -235,7 +284,7 @@ class Board(): if prob > 0: result.update({p : prob}) - self.verify() + #self.verify() return result @@ -260,7 +309,7 @@ class Board(): for i in range(len(p.types)): t = p.types[i] prob = 0.5 - if t == "unknown" or p.types_revealed[i] == False: + if t == "unknown" or p.types[i][0] == '?': total_types = 0 for t2 in self.unrevealed_types[p.colour].keys(): total_types += self.unrevealed_types[p.colour][t2] @@ -276,7 +325,7 @@ class Board(): for point in self.possible_moves(p, reject_allied): result[point[0]][point[1]] += prob - self.verify() + #self.verify() p.current_type = "unknown" return result @@ -288,7 +337,7 @@ class Board(): if t == state: result += prob continue - if t == "unknown" or p.types_revealed[i] == False: + if t == "unknown" or p.types[i][0] == '?': total_prob = 0 for t2 in self.unrevealed_types[p.colour].keys(): total_prob += self.unrevealed_types[p.colour][t2] @@ -302,10 +351,25 @@ class Board(): # This is probably inefficient, but I looked at some sample chess games and they seem to actually do things this way # reject_allied indicates whether squares occupied by allied pieces will be removed # (set to false to check for defense) - def possible_moves(self, p, reject_allied = True): - result = [] + def possible_moves(self, p, reject_allied = True, state=None): if p == None: + raise Exception("SANITY: No piece") + + + + if state != None and state != p.current_type: + old_type = p.current_type + p.current_type = state + result = self.possible_moves(p, reject_allied, state=None) + p.current_type = old_type return result + + if p.possible_moves != None: + return p.possible_moves + + + result = [] + if p.current_type == "unknown": @@ -377,7 +441,9 @@ class Board(): if g != None and (g.colour == p.colour and reject_allied == True): result.remove(point) # Remove allied pieces - self.verify() + #self.verify() + + p.possible_moves = result return result @@ -401,8 +467,49 @@ class Board(): return p + # Returns "white", "black" or "DRAW" if the game should end + def end_condition(self): + if self.king["white"] == None: + if self.king["black"] == None: + return "DRAW" # This shouldn't happen + return "black" + elif self.king["black"] == None: + return "white" + elif len(self.pieces["white"]) == 1 and len(self.pieces["black"]) == 1: + return "DRAW" + elif self.max_moves != None and self.moves > self.max_moves: + return "DRAW" + return None # I typed the full statement about 30 times before writing this function... def on_board(self, x, y): return (x >= 0 and x < w) and (y >= 0 and y < h) + + # Pushes a move temporarily + def push_move(self, piece, x, y): + target = self.grid[x][y] + self.move_stack.append([piece, target, piece.x, piece.y, x, y]) + [piece.x, piece.y] = [x, y] + self.grid[x][y] = piece + self.grid[piece.x][piece.y] = None + + for p in self.pieces["white"] + self.pieces["black"]: + p.possible_moves = None + + # Restore move + def pop_move(self): + #print str(self.move_stack) + [piece, target, x1, y1, x2, y2] = self.move_stack[len(self.move_stack)-1] + self.move_stack = self.move_stack[:-1] + piece.x = x1 + piece.y = y1 + self.grid[x1][y1] = piece + if target != None: + target.x = x2 + target.y = y2 + self.grid[x2][y2] = target + + for p in self.pieces["white"] + self.pieces["black"]: + p.possible_moves = None +