[w,h] = [8,8] # Width and height of board(s)
+always_reveal_states = False
+
# Class to represent a quantum chess board
class Board():
# Initialise; if master=True then the secondary piece types are assigned
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"]
+ if style == "empty":
+ return
+
# Add all the pieces with known primary types
for i in range(0, 2):
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)
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):
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]):
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")
+
self.grid[x][y] = None
taken = self.grid[x2][y2]
if taken != None:
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
if prob > 0:
result.update({p : prob})
- self.verify()
+ #self.verify()
return result
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]
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
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]
# 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":
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
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
+