def main(): board = ChessBoard() change_settings = 0 while True: if change_settings == 0: num_player = get_user_response("How many players do you want (1-2)?: ", "012") if num_player == 0: p1 = CPUPlayer(Color.WHITE) p2 = CPUPlayer(Color.BLACK) elif num_player == 1: who_first = get_user_response("Do you want to be White(W) or Black(B)?: ", "WB") difficulty = get_user_response("How good do you want the computer to play (1-9): ", "123456789") if who_first == 0: p1 = HumanPlayer(Color.WHITE) p2 = CPUPlayer(Color.BLACK) else: p1 = CPUPlayer(Color.WHITE) p2 = HumanPlayer(Color.BLACK) else: p1 = HumanPlayer(Color.WHITE) p2 = HumanPlayer(Color.BLACK) board.init_board() play_game(p1, p2, board) pa_resp = get_user_response("Do you want to play again Y/N: ", "YN") if pa_resp == 1: # break if user wanted to quit break change_settings = get_user_response("Do you want to change the settings Y/N: ", "YN") del board del p1 del p2
def PlaySingleMatch(self): self.Board = ChessBoard(0) #reset board currentPlayerIndex = 0 turnCount = 0 while not self.Rules.IsCheckmate( self.Board.GetState(), self.player[currentPlayerIndex].color): board = self.Board.GetState() currentColor = self.player[currentPlayerIndex].GetColor() #hardcoded so that player 1 is always white if currentColor == 'white': turnCount = turnCount + 1 if turnCount % 10 == 0: print " %d" % turnCount, if turnCount > 200: return ( turnCount, -1 ) #Call it a draw... otherwise some games can go on forever. moveTuple = self.player[currentPlayerIndex].GetMove( self.Board.GetState(), currentColor) moveReport = self.Board.MovePiece( moveTuple ) #moveReport = string like "White Bishop moves from A1 to C3" (+) "and captures ___!" #print moveReport currentPlayerIndex = ( currentPlayerIndex + 1 ) % 2 #this will cause the currentPlayerIndex to toggle between 1 and 0 winnerIndex = (currentPlayerIndex + 1) % 2 return (turnCount, winnerIndex)
def playRandom(): cb = ChessBoard() return_value = playRandomGame(cb) printBoard(cb) print ("\n%s win one board. last move is %s %s, return value is %d" % ( transferSymbol(cb.get_winner()), numToAlp(cb.get_lastmove()[0]), numToAlp(cb.get_lastmove()[1]), return_value))
def rnd_game(): SCREEN_SIZE = (base_size * 3, base_size * 3) pygame.init() screen = pygame.display.set_mode(SCREEN_SIZE, RESIZABLE, 32) cb = ChessBoard() sa = StatisticAgent(cb, cb.player1_flag, cb.player2_flag) draw_background(screen, (100,200,100), SCREEN_SIZE[0], SCREEN_SIZE[1]) finished = False game_step = 0 while True: event = pygame.event.wait() if event.type == QUIT: exit() pressed_mouse = pygame.mouse.get_pressed() if pressed_mouse[0] and game_step % 2 + 1 == sa.enemy_flag and finished == False: x, y = pygame.mouse.get_pos() r, c = xy2rc(x, y) if cb.is_empty(r, c): winner = cb.make_a_move(r, c, sa.enemy_flag, True) game_step += 1 draw_chessboard(screen, cb) if winner != None: finished = True if (game_step % 2) + 1 == sa.my_flag and finished == False: winner = cb.make_rnd_move(sa.my_flag) game_step += 1 draw_chessboard(screen, cb) if winner != None: finished = True pygame.display.update()
def statistic_test(): cb = ChessBoard() sa = StatisticAgent(cb, cb.player1_flag, cb.player2_flag) cb.print_board() for i in range(9): winner = sa.make_statistic_move(cb, sa.my_flag) cb.print_board() if winner != None and winner != -1: print winner, "wins!" break elif winner == -1: print "The game is already over." break r, c = 0, 0 while True: move = [int(i) for i in raw_input("your move:").split()] r, c = move[0], move[1] if cb.is_empty(r, c): break else: print "[%d, %d] is occupied! Try again."%(r, c) winner = cb.make_a_move(r, c, sa.enemy_flag, True) cb.print_board() if winner == cb.player1_flag or winner == cb.player2_flag: print winner, "wins!" break elif winner == cb.draw_flag: print "There is a draw." break
def test_Checkmate(self, mockGetListOfValidMoves): "Unit test for ChessRules method: IsCheckmate" # NOTE 1: We only check that there are valid moves for a given color # NOTE 2: We are NOT checking the setting color logic in this unit test. You need to write another unit test for this logic. # Creating objects of Chessboard and ChessRules class and calling IsCheckmate function with each piece for initial position and "black" color cb = ChessBoard( 0) #Create a chess board object with the initial position chess_rules_obj = ChessRules.ChessRules() chess_rules_obj.IsCheckmate(cb.GetState(), "black") # Create expected_arg_calls list which is supposed to be called with GetListOfValidMoves for initial position # IsCheckmate calls GetListOfValidMoves with arguments: board, color (who is to play?) and co-ordinates of a square with a piece on it expected_arg_calls = [] for row in range(0, 2): for col in range(0, 8): expected_arg_calls.append( mock.call(cb.GetState(), 'black', (row, col))) # Assert that the mockGetListOfValidMoves.call_args_list matches expected_arg_calls self.assertEqual(mockGetListOfValidMoves.call_args_list, expected_arg_calls) # DID YOU KNOW? # assert_any_call can be used to assert a method that was called at least once with some arguments #mockGetListOfValidMoves.assert_any_call(cb.GetState(),"black",(1,6)) # DID YOU KNOW? # call_count can be used to check the number of times your mocked method was called self.assertEqual(mockGetListOfValidMoves.call_count, 16)
def move(self, board: ChessBoard) -> bool: while True: resp_string = self.ask_for_player_move() if resp_string == "q": return True # turn response into list of 4 ascii values resp = [ord(c) for c in resp_string] ord_string = "a1a1" origin = [ord(c) for c in ord_string ] # create list for origin ascii values diff = [] # subtract inputted coordinates from origin to get coordinates as 0 based index in 2d list zip_object = zip(resp, origin) for resp_i, origin_i in zip_object: diff.append(resp_i - origin_i) if board.is_valid_move(diff[1], diff[0], diff[3], diff[2], self.player_color): # Have the board make the move and return True if checkmate was a achieved and false if it wasn't # if move failed then loop is continued and nothing is returned move_type = board.move_piece(diff[1], diff[0], diff[3], diff[2], self.color_to_string(True)) if move_type == MoveType.CHECKMATE: return True elif move_type == MoveType.MOVE_PASSED: return False else: print("Error invalid move. Please try again!")
def test_putpiece1(self): cb = ChessBoard() self.assertEqual(0, cb.put_piece(0, 0, 1)) self.assertEqual(-2, cb.put_piece(0, 0, 1)) self.assertEqual(-1, cb.put_piece(-1, 0, 1)) self.assertEqual(-1, cb.put_piece(0, 16, 1))
class PythonChessMain: def __init__(self, options): if options.debug: self.Board = ChessBoard(2) self.debugMode = True else: self.Board = ChessBoard( 0 ) # 0 for normal board setup; see ChessBoard class for other options (for testing purposes) self.debugMode = False def SetUp(self, options): # gameSetupParams: Player 1 and 2 Name, Color, Human/AI level self.guitype = "pygame" if options.old: self.Gui = ChessGUI_pygame(0) else: self.Gui = ChessGUI_pygame(1) def MainLoop(self): for x in range(10): self.Board.generate() self.Board.GetState() self.Gui.Draw(board) time.sleep(2) self.Gui.EndGame(board)
def test_putpiece2(self): cb = ChessBoard() muser = 1 for i in xrange(4): for j in xrange(15): return_value = cb.put_piece(i, j, muser) self.assertEqual(0, return_value) muser = 2 if muser == 1 else 1
def __init__(self,options): if options.debug: self.Board = ChessBoard(2) self.debugMode = True else: self.Board = ChessBoard(0)#0 for normal board setup; see ChessBoard class for other options (for testing purposes) self.debugMode = False self.Rules = ChessRules()
def __init__(self, options): if options.debug: self.Board = ChessBoard(2) self.debugMode = True else: self.Board = ChessBoard( 0 ) # 0 for normal board setup; see ChessBoard class for other options (for testing purposes) self.debugMode = False
def __init__(self, options): if options.debug: self.Board = ChessBoard(2) self.debugMode = True else: self.Board = ChessBoard( 6 ) #6 for Checkmate with knights setup; see ChessBoard class for other options (for testing purposes) self.debugMode = False self.Rules = ChessRules()
def __init__(self, options): if options.debug: self.Board = ChessBoard(2) self.debugMode = True else: self.Board = ChessBoard( 7 ) #7 for Bishops Checkmate setup; see ChessBoard class for other options (for testing purposes) self.debugMode = False self.Rules = ChessRules()
def __init__(self, room_id_): self.play_users = [] self.position2users = {} # 1 black role 2 white role self.room_id = room_id_ self.users = [] self.max_player_num = 2 self.max_user_num = 10000 self.board = ChessBoard() self.status_signature = None self.set_changed() self.chess_folder = 'chess_output' # self.game_status = GameRoom.GAME_STATUS_NOTBEGIN self.ask_take_back = 0
def IsInCheck(self,chessboard): # Now we're checking for any black moves that take the king. We want to consider the opponent of "color"'s moves. chessboard.Rotate(skipsq=True) check=False for move in self.GetAllValidMoveNumbers(chessboard,skipCheckTest=True): newboard = ChessBoard([chessboard.board,[],0]) newboard.MovePiece(move,skipsq=True) if 'k' not in newboard.board: check=True break chessboard.Rotate(skipsq=True) return check
def play_game(p1: Player, p2: Player, board: ChessBoard): p1.reset_game() p2.reset_game() cur_player = 0 quit_game = False while True: board.display_board() if quit_game: break if cur_player == 0: quit_game = p1.move(board) else: quit_game = p2.move(board) cur_player = 1 - cur_player # switch whose turn it is print("")
def syncBoard(self, m): if not isinstance(m, ChessMoveMessage): return chess = ChessBoard() if isinstance(m, ChessMoveMessage): for move in m.history: chess.addTextMove(move) board = chess.getBoard() cboard = self.strategy.board() for row, rank in enumerate(board): for col, square in enumerate(rank): cboard.setPiece(row, col, square)
def __init__(self,aSkillLevel,aMoveTime): """ Create an object to hold the game state Use Chessboard library for logic """ print "Game State Initilized" self.chessGame = ChessBoard() self.chessGame.resetBoard() self.chessGame.printBoard() self.moveTime = aMoveTime #Used to store movetime self.skillLevel = aSkillLevel #Used to store skill level self.gameMoves = [] #Used to store all moves in game self.saveFileExt = ".txt" self.saveFilePath = "" self.startPos = "startpos" #Used to store the start position or fen string
def __init__(self, player_white, player_black): self.board = ChessBoard() self.board.set_start_position() self.player_white = player_white self.player_black = player_black self.move_number = 1 self.previous_board = copy.deepcopy(self.board) self.result_notation_text = '' self.is_white_check = False self.is_black_check = False self.possible_white_long_castling = True self.possible_white_short_castling = True self.possible_black_long_castling = True self.possible_black_short_castling = True
def createGame(self, game_id, p1, p2): game = { 'player 1' : p1, 'player -1' : p2, 'board' : ChessBoard() } self.__editGames(game_id, game)
def add_coord_to_path(self,path, r1,c1, r2,c2): # cheking if the piece captures the bait if(ChessBoard.piece_val(self.board[r1,c1])==6 and self.board[r2,c2]==self.enm_bait): en_pass_take = True # temporary removing enemy pawn that used en_passant and get captured self.board.put_at(r1,c2,0) else: en_pass_take = False temp_piece = self.board[r2,c2] self.board.transact(r1,c1, r2,c2) attk_zone = self.get_weakness() k_val = np.argwhere(ChessBoard.PIECES == ('WK' if self.color == 'WHITE' else 'BK'))[0,0] # print(k_val) k_pos = np.argwhere(self.board.board == k_val)[0] # print(k_pos) # if move is not getting king under attack then add path if attk_zone[k_pos[0],k_pos[1]] == 0: # print("True") path.append((r2,c2)) self.board.transact(r2,c2, r1,c1) self.board.put_at(r2,c2, temp_piece) if en_pass_take: # putting the enemy pawn back self.board.put_at(r1,c2,12 if self.color == 'WHITE' else 6)
def playMuch(num): oi = 0 for i in xrange(num): cb = ChessBoard() playRandomGame(cb) oi += cb.move_num print(oi / num)
def onChessMessage(self, m): log.info(str(m)) chess = ChessBoard() if not isinstance(m, ChessMoveMessage): self.clear() return algebraicNotationMoves = [] for move in m.history: chess.addTextMove(move) algebraicNotationMoves.append(chess.getLastTextMove(ChessBoard.AN)) stockfishFEN, legalMoves, scores, pctM, pctE1, pctE2, total = self.stockfish.eval( algebraicNotationMoves) ## Call: ## lm(formula = whiteWins ~ s, data = a, na.action = na.exclude) ## ## Residuals: ## Min 1Q Median 3Q Max ## -0.7457 -0.4437 -0.1217 0.4577 0.8783 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 0.4337105 0.0012811 338.5 <2e-16 *** ## s 0.1247885 0.0008928 139.8 <2e-16 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.4669 on 137618 degrees of freedom ## (70 observations deleted due to missingness) ## Multiple R-squared: 0.1243, Adjusted R-squared: 0.1243 ## F-statistic: 1.953e+04 on 1 and 137618 DF, p-value: < 2.2e-16 ##log.info(scores) s = total s = min(s, 2.5) s = max(s, -2.5) self.feat['total'] = total self.feat['s'] = s self.feat['pctM'] = pctM self.fp = (0.4337105 + 0.1247885 * s) * 100 self.fp = min(self.fp, 100) self.fp = max(self.fp, 0)
def simulation(self, r, c): sim_board = copy.deepcopy(self.chess_board.board) sim_chess_board = ChessBoard(sim_board) winner = sim_chess_board.make_a_move(r, c, self.my_flag) if winner == self.chess_board.draw_flag: return 0.0 elif winner == self.my_flag: return 1.1 win_times = 0 lost_times = 0 for i in range(self.sim_times): sim_board2 = copy.deepcopy(sim_board) sim_chess_board2 = ChessBoard(sim_board2) while True: winner = sim_chess_board2.make_rnd_move(self.enemy_flag) if winner == self.enemy_flag: lost_times += 1 break elif winner == self.chess_board.draw_flag: break winner = sim_chess_board2.make_rnd_move(self.my_flag) if winner == self.my_flag: win_times += 1 break elif winner == self.chess_board.draw_flag: break return 1.0 * (self.sim_times - lost_times) / self.sim_times
def onChessMessage(self,m): log.info(str(m)) chess = ChessBoard() if not isinstance(m, ChessMoveMessage): self.clear() return algebraicNotationMoves = [] for move in m.history: chess.addTextMove(move) algebraicNotationMoves.append(chess.getLastTextMove(ChessBoard.AN)) stockfishFEN, legalMoves, scores, pctM, pctE1, pctE2, total = self.stockfish.eval(algebraicNotationMoves) ## Call: ## lm(formula = whiteWins ~ s, data = a, na.action = na.exclude) ## ## Residuals: ## Min 1Q Median 3Q Max ## -0.7457 -0.4437 -0.1217 0.4577 0.8783 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 0.4337105 0.0012811 338.5 <2e-16 *** ## s 0.1247885 0.0008928 139.8 <2e-16 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.4669 on 137618 degrees of freedom ## (70 observations deleted due to missingness) ## Multiple R-squared: 0.1243, Adjusted R-squared: 0.1243 ## F-statistic: 1.953e+04 on 1 and 137618 DF, p-value: < 2.2e-16 ##log.info(scores) s = total s = min(s, 2.5) s = max(s, -2.5) self.feat['total'] = total self.feat['s'] = s self.feat['pctM'] = pctM self.fp = (0.4337105 + 0.1247885 * s)*100 self.fp = min(self.fp, 100) self.fp = max(self.fp, 0)
def parse_score(line): analysis_board = ChessBoard() analysis_board.setFEN(self.chessboard.getFEN()) tokens = line.split() try: score_index = tokens.index('score') except ValueError: score_index = -1 score = None move_list = [] if score_index != -1 and tokens[score_index + 1] == "cp": score = float(tokens[score_index + 2]) / 100 * 1.0 try: line_index = tokens.index('pv') for mv in tokens[line_index + 1:]: analysis_board.addTextMove(mv) move_list.append(analysis_board.getLastTextMove()) except ValueError: line_index = -1 variation = self.generate_move_list( move_list, start_move_num=self.chessboard.getCurrentMove() + 1) if line_index != -1 else None del analysis_board if variation and score: return move_list, "[b]%s[/b][color=0d4cd6][ref=engine_toggle] Stop[/ref][/color]\n[color=77b5fe]%s[/color]" % ( score, "".join(variation))
def __init__(self, dad=None, fromPiece=(0,0), toPiece=(0,0), board=ChessBoard().squares, lvl=0): self.dad = dad self.fromPiece = fromPiece self.toPiece = toPiece self.board = board self.color = self.setColor(fromPiece) self.score = self.cScore() self.lvl = lvl self.children = [] del self.board
def __init__(self): pygame.init() self.game_display = pygame.display.set_mode((900, 650)) pygame.display.set_caption('Chess') self.settings = {'board_image': 'images/orange_board.png'} self.board_image = pygame.image.load(self.settings['board_image']) self.clock = pygame.time.Clock() self.chess_board = ChessBoard() self.curr_selected_piece = None self.curr_poss_moves = [] self.all_poss_moves = self.get_all_poss_moves() self.white_pieces_taken_images = [] self.black_pieces_taken_images = [] self.play_game()
def test_called_with_args(self, mockGetListOfValidMoves): "Unit test for ChessRules method: IsCheckmate" # Creating objects of Chessboard and ChessRules class and calling IsCheckmate function with each piece for initial position and "black" color cb = ChessBoard( 0) # Create a chess board object with the initial position chess_rules_obj = ChessRules.ChessRules() chess_rules_obj.IsCheckmate(cb.GetState(), "black") # Create expected_arg_calls list which is supposed to be called with GetListOfValidMoves for initial position # IsCheckmate calls GetListOfValidMoves with arguments: board, color (who is to play?) and co-ordinates of a square with a piece on it expected_arg_calls = [] for row in range(0, 2): for col in range(0, 8): expected_arg_calls.append( mock.call(cb.GetState(), 'black', (row, col))) # assert that method was called at least once with some argument mockGetListOfValidMoves.assert_any_call(cb.GetState(), "black", (1, 6))
def parse_score(line): analysis_board = ChessBoard() analysis_board.setFEN(self.chessboard.getFEN()) tokens = line.split() try: score_index = tokens.index('score') except ValueError: score_index = -1 score = None move_list = [] if score_index!=-1 and tokens[score_index+1]=="cp": score = float(tokens[score_index+2])/100*1.0 try: line_index = tokens.index('pv') for mv in tokens[line_index+1:]: analysis_board.addTextMove(mv) move_list.append(analysis_board.getLastTextMove()) except ValueError: line_index = -1 variation = self.generate_move_list(move_list,start_move_num=self.chessboard.getCurrentMove()+1) if line_index!=-1 else None del analysis_board if variation and score: return move_list, "[b]%s[/b][color=0d4cd6][ref=engine_toggle] Stop[/ref][/color]\n[color=77b5fe]%s[/color]" %(score,"".join(variation))
def __init__(self, server_url): self.session = requests.Session() self.session.cookies = cookielib.CookieJar() agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.1.2.3000 Chrome/55.0.2883.75 Safari/537.36' self.headers = { "Host": server_url, "Origin": server_url, "Referer": server_url, 'User-Agent': agent } self.server_url = server_url self.board = ChessBoard() self.last_status_signature = ""
def onChessMessage(self, m): log.info(str(m)) chess = ChessBoard() if not isinstance(m, ChessMoveMessage): self.materialScore = 0 return for move in m.history: chess.addTextMove(move) values = {"P": 1, "N": 3, "B": 3, "R": 5, "Q": 9, "K": 1} board = chess.getBoard() W, B = 0, 0 for rank in board: for square in rank: if square != ".": if square.isupper(): W += values[square] else: B += values[square.upper()] self.materialScore = W - B log.info("materialScore = %d" % self.materialScore)
def syncStockfish(self, m): if not isinstance(m, ChessMoveMessage) or not self.stockfish: return chess = ChessBoard() algebraicNotationMoves = [] for move in m.history: chess.addTextMove(move) algebraicNotationMoves.append(chess.getLastTextMove(ChessBoard.AN)) fen, legalMoves, scores, pctM, pctE1, pctE2, total = self.stockfish.eval(algebraicNotationMoves) sf = self.strategy.stockfish() sf.reset() sf.setFEN(fen) sf.setLegalMoves(legalMoves) sf.setTotal(pctM, pctE1, pctE2, total) for scoreType, scoreList in scores.iteritems(): for scoreSubtype, score in scoreList.iteritems(): if not math.isnan(score): sf.setScore(scoreType, scoreSubtype, score)
def onChessMessage(self,m): log.info(str(m)) chess = ChessBoard() if not isinstance(m, ChessMoveMessage): self.materialScore = 0 return for move in m.history: chess.addTextMove(move) values = {"P": 1, "N": 3, "B": 3, "R": 5, "Q": 9, "K": 1} board = chess.getBoard() W,B = 0,0 for rank in board: for square in rank: if square != ".": if square.isupper(): W += values[square] else: B += values[square.upper()] self.materialScore = W-B log.info("materialScore = %d" % self.materialScore)
def main(): board = ChessBoard() loadStandardGame(board) board.printBoard() print("Enter moves as coordinates pair (eg: 7a to 6a") print("Type 'quit' to exit!") print("White starts!") while True: start = input("start: ") end = input("end: ") if start.lower() == 'quit' or end.lower() == 'quit': break board.moveOnBoard(start, end) board.printBoard() print("Next player turn!")
def __init__(self, x_size, y_size, log=None, initial_position=INITIAL_POSITION, max_pending_moves=MAX_PENDING_MOVES): """ max_pending_moves : * Maximum number of last moves awaiting for mandatory changes before calling for help * Maximum number of moves a non-matched change waits before calling for help """ # FIXME x_size and y_size are not verified against initial_position self.log_function = log or self.defaultLogFunction self.initial_position = initial_position self.max_pending_moves = max_pending_moves self.chessboard = ChessBoard(x_size, y_size) self.chessboard.initializeFEN(initial_position) self.move_history = [] self.change_buffer = [] self.pending_changes = [] self.recording = False self.name = None self.last_ambiguous_change = None initial_repr = initial_position.split("/") initial_repr.reverse() self.change_history = [PhysicalBoardChange(0, None, None, None, initial_repr)] self.change_history_index = 0
def mainLooptemp(self): chess = ChessBoard() clock = pygame.time.Clock() screen = pygame.display.set_mode((480, 480),1) pygame.display.set_caption('ChessBoard Client') view = PyGameWindowView(chess,screen) controller = Controller(chess) running = True # paired_piece_weights_1 = run_genetic_algorithms.build_random_pair_piece_dict() # paired_piece_weights_2 = run_genetic_algorithms.build_random_pair_piece_dict() player_1 = Human(ChessBoard.WHITE) # player_2 = Human(ChessBoard.BLACK) # AI1ply = 2 # player_1 = ChessAI(ChessBoard.WHITE,chess,evaluation_functions.terminal_eval_simple, # prune_functions.never_prune,QFunctions.simple_end_game,paired_piece_weights_1,AI1ply) AI2ply = 2 player_2 = ChessAI(ChessBoard.BLACK,chess,evaluation_functions.terminal_eval, prune_functions.never_prune,QFunctions.no_extension,None,AI2ply) ## AI_color = ChessBoard.BLACK # player_color = ChessBoard.WHITE # human_player = Player(player_color) ## AI = (AI_color) # player_2_color = ChessBoard.BLACK # human_player_2 = Player(player_2_color) while running: clock.tick(30) if chess.getTurn() == player_1.color and not chess.isGameOver(): if type(player_1) == Human: for event in pygame.event.get(): if event.type == QUIT: running = False pygame.quit() return else: controller.handle_event(event) else: print "AI 1 (WHITE) making turn" player_1.make_next_move() chess.moveNumber += 1 elif chess.getTurn() == player_2.color and not chess.isGameOver(): if type(player_2) == Human: for event in pygame.event.get(): if event.type == QUIT: running = False pygame.quit() return else: controller.handle_event(event) else: print "AI 2 (BLACK) making turn" player_2.make_next_move() chess.moveNumber += 1 #multithread in python to be able to make calculations and quit during player's turn # if chess.getTurn() == AI.color: # turn = machine.get_turn() # board.updatewithMachine'sturn if chess.isGameOver(): view.title_game_display(chess) chess.validMoves = [] chess.markPos[0] = -1 chess.markPos[1] = -1 for event in pygame.event.get(): if event.type == QUIT: running = False pygame.quit() return else: pygame.display.set_caption('ChessBoard Client') view.draw(chess) pygame.display.flip() pygame.quit()
def mainLoop(self): pygame.init() pieces = {} chess = ChessBoard() board = chess.getBoard() turn = chess.getTurn() screen = pygame.display.set_mode((480, 480),1) pygame.display.set_caption('ChessBoard Client') # load all images pieces = [{},{}] pieces[0]["r"] = pygame.image.load("./img/brw.png") pieces[0]["n"] = pygame.image.load("./img/bnw.png") pieces[0]["b"] = pygame.image.load("./img/bbw.png") pieces[0]["k"] = pygame.image.load("./img/bkw.png") pieces[0]["q"] = pygame.image.load("./img/bqw.png") pieces[0]["p"] = pygame.image.load("./img/bpw.png") pieces[0]["R"] = pygame.image.load("./img/wrw.png") pieces[0]["N"] = pygame.image.load("./img/wnw.png") pieces[0]["B"] = pygame.image.load("./img/wbw.png") pieces[0]["K"] = pygame.image.load("./img/wkw.png") pieces[0]["Q"] = pygame.image.load("./img/wqw.png") pieces[0]["P"] = pygame.image.load("./img/wpw.png") pieces[0]["."] = pygame.image.load("./img/w.png") pieces[1]["r"] = pygame.image.load("./img/brb.png") pieces[1]["n"] = pygame.image.load("./img/bnb.png") pieces[1]["b"] = pygame.image.load("./img/bbb.png") pieces[1]["k"] = pygame.image.load("./img/bkb.png") pieces[1]["q"] = pygame.image.load("./img/bqb.png") pieces[1]["p"] = pygame.image.load("./img/bpb.png") pieces[1]["R"] = pygame.image.load("./img/wrb.png") pieces[1]["N"] = pygame.image.load("./img/wnb.png") pieces[1]["B"] = pygame.image.load("./img/wbb.png") pieces[1]["K"] = pygame.image.load("./img/wkb.png") pieces[1]["Q"] = pygame.image.load("./img/wqb.png") pieces[1]["P"] = pygame.image.load("./img/wpb.png") pieces[1]["."] = pygame.image.load("./img/b.png") clock = pygame.time.Clock() posRect = pygame.Rect(0,0,60,60) mousePos = [-1,-1] markPos = [-1,-1] validMoves = [] gameResults = ["","WHITE WINS!","BLACK WINS!","STALEMATE","DRAW BY THE FIFTHY MOVES RULE","DRAW BY THE THREE REPETITION RULE"] while 1: clock.tick(30) for event in pygame.event.get(): if event.type == QUIT: return elif event.type == KEYDOWN: if event.key == K_ESCAPE: return elif event.key == K_LEFT: chess.undo() elif event.key == K_RIGHT: chess.redo() elif event.unicode in ("f","F"): print chess.getFEN() elif event.unicode in ("a","A"): an = chess.getAllTextMoves(chess.AN) if an: print "AN: " + ", ".join(an) elif event.unicode in ("s","S"): san = chess.getAllTextMoves(chess.SAN) if san: print "SAN: " + ", ".join(san) elif event.unicode in ("l","L"): lan = chess.getAllTextMoves(chess.LAN) if lan: print "LAN: " + ", ".join(lan) board = chess.getBoard() turn = chess.getTurn() markPos[0] = -1 validMoves = [] if not chess.isGameOver(): if event.type == MOUSEMOTION: mx = event.pos[0] my = event.pos[1] mousePos[0] = mx/60 mousePos[1] = my/60 elif event.type == MOUSEBUTTONDOWN: if mousePos[0] != -1: if markPos[0] == mousePos[0] and markPos[1] == mousePos[1]: markPos[0] = -1 validMoves = [] else: if (turn==ChessBoard.WHITE and board[mousePos[1]][mousePos[0]].isupper()) or \ (turn==ChessBoard.BLACK and board[mousePos[1]][mousePos[0]].islower()): markPos[0] = mousePos[0] markPos[1] = mousePos[1] validMoves = chess.getValidMoves(tuple(markPos)) else: if markPos[0] != -1: res = chess.addMove(markPos,mousePos) if not res and chess.getReason() == chess.MUST_SET_PROMOTION: chess.setPromotion(chess.QUEEN) res = chess.addMove(markPos,mousePos) if res: #print chess.getLastMove() print chess.getLastTextMove(chess.SAN) board = chess.getBoard() turn = chess.getTurn() markPos[0] = -1 validMoves = [] if chess.isGameOver(): pygame.display.set_caption("Game Over! (Reason:%s)" % gameResults[chess.getGameResult()]) validMove = [] markPos[0] = -1 markPos[1] = -1 else: pygame.display.set_caption('ChessBoard Client') y = 0 for rank in board: x = 0 for p in rank: screen.blit(pieces[(x+y)%2][p],(x*60,y*60)) x+=1 y+=1 if markPos[0] != -1: posRect.left = markPos[0]*60 posRect.top = markPos[1]*60 pygame.draw.rect(screen, (255,255,0),posRect, 4) for v in validMoves: posRect.left = v[0]*60 posRect.top = v[1]*60 pygame.draw.rect(screen, (255,255,0),posRect, 4) pygame.display.flip()
class GameState: def __init__(self,aSkillLevel,aMoveTime): """ Create an object to hold the game state Use Chessboard library for logic """ print "Game State Initilized" self.chessGame = ChessBoard() self.chessGame.resetBoard() self.chessGame.printBoard() self.moveTime = aMoveTime #Used to store movetime self.skillLevel = aSkillLevel #Used to store skill level self.gameMoves = [] #Used to store all moves in game self.saveFileExt = ".txt" self.saveFilePath = "" self.startPos = "startpos" #Used to store the start position or fen string def loadGameState(self,aFileName): """ Load from file, game should be reset first """ if len(self.gameMoves) == 0: #Game moves must be empty to load game try: aFile = open(self.saveFilePath + aFileName + self.saveFileExt,'r') for aLine in aFile: if aLine[0] != '#': self.gameMoves.append(aLine[0:4]) self.chessGame.addTextMove(aLine) aFile.close() #Show moves self.chessGame.printBoard() except IOError: print "File Error" else: #Game moves not empty print "Can't load game, has it been reset?" def loadFen(self,aFileName): """ Load from file, game should be reset first """ if len(self.gameMoves) == 0: #Game moves must be empty to load game try: fenInstruc = "" aFile = open(self.saveFilePath + aFileName + self.saveFileExt,'r') for aLine in aFile: if aLine[0] == '$': removeChar = aLine.strip('$') #remove the first char removeChar = removeChar.strip('\n') fenInstruc = fenInstruc + removeChar + " " #build any instructions for game if aLine[0] == '!': fenLine = aLine #found line with fen code fenLine = fenLine.strip('!') aFile.close() #Load fen line on to game board self.chessGame.setFEN(fenLine) print fenInstruc self.chessGame.printBoard() self.startPos = "fen " + fenLine #set startpos to fen line except IOError: print "File Error" else: #Game moves not empty print "Can't load FEN file, has it been reset?" def saveGameState(self,aFileName): """ Save game moves to file """ print "Saving game state" if len(self.gameMoves) > 0: #Have a game to save aFile = open(self.saveFilePath + aFileName + self.saveFileExt,'w') for aMove in self.gameMoves: aFile.write(aMove + "\n") aFile.close() else: #No moves stored, nothing to save print "No game to save" def getSkillLevel(self): """ Return game state skill level as a string """ return str(self.skillLevel) def getMoveTime(self): """ Return movetime as a string """ return str(self.moveTime) def getMoveList(self): """ Return moves in list as a string """ moveString = "" for aMove in self.gameMoves: moveString = moveString + " " + aMove return moveString def addMove(self,chessMove): """ Add chess move to game state """ theMove = chessMove.lower() if self.chessGame.addTextMove(theMove) == False: #Invalid move errorText = "Error in GameState:" + str(self.chessGame.getReason()) + " " + theMove print errorText self.chessGame.printBoard() theMove = "xxxx" #return something to catch if the move had an error else: #Move OK self.chessGame.printBoard() #Add the move to the list of moves for this game self.gameMoves.append(theMove) return theMove def undoMove(self): """ Undo the last move. Will need to undo last two moves as the last move will be the engine's and then the players """ if len(self.gameMoves) > 1: self.gameMoves.pop() self.gameMoves.pop() self.chessGame.undo() self.chessGame.undo() self.chessGame.printBoard() print "Last move undo" else: print "No moves to undo!" def getStartPos(self): """ Return the current start positionof the game this will be 'startpos' or fen <some fen string> """ return self.startPos def findLocation(self,aPiece): """ Find the location of a Piece orPieces """ pieceList = [] rowNumber = 8 theBoard = self.chessGame.getBoard() for eachRow in theBoard: columnNumber = 1 for piece in eachRow: if piece == aPiece: value = self.colToLetter(columnNumber) + str(rowNumber) pieceList.append(value) columnNumber = columnNumber + 1 rowNumber = rowNumber - 1 #rows inverted to match a chess board print pieceList def colToLetter(self,aNumber): """ Convert column number to a letter """ letter ="" if aNumber == 1: letter = 'A' elif aNumber == 2: letter = 'B' elif aNumber == 3: letter = 'C' elif aNumber == 4: letter = 'D' elif aNumber == 5: letter = 'E' elif aNumber == 6: letter = 'F' elif aNumber == 7: letter = 'G' elif aNumber == 8: letter = 'H' return letter
def mainLoop(self): print("White Player, choose an army:") print("1. Classic 2. Nemesis 3. Empowered") print("4. Reaper 5. Two Kings 6. Animals") while True: print('Type the number, not the name.') userInput = getpass.getpass('> ') if userInput in string.digits: if int(userInput) < 7: if int(userInput) > 0: break print('Please enter only one of the above.') else: print('Please enter only one character') wArmy = userInput print("Black Player, choose an army:") print("1. Classic 2. Nemesis 3. Empowered") print("4. Reaper 5. Two Kings 6. Animals") while True: print('Type the number, not the name.') userInput = getpass.getpass('> ') if userInput in string.digits: if int(userInput) < 7: if int(userInput) > 0: break print('Please enter only one of the above.') else: print('Please enter only one of the above.') bArmy = userInput turn = 0 chess = ChessBoard(int(wArmy), int(bArmy)) prototype = [] prototype.append('[Event "Sample Games"]') prototype.append('[Site "' + 'Fantasy Strike Website' '\"]') prototype.append('[Date "' + ".".join((time.strftime("%Y"), time.strftime("%m"), time.strftime("%d"))) + '"]') prototype.append('[Round "' + '-' + '"]') prototype.append('[White "' + chess.army_name_dict[int(wArmy)] + '"]') prototype.append('[Black "' + chess.army_name_dict[int(bArmy)] + '"]') while True: turn = chess.getTurn() board = chess.printBoard() for row in board: print(row) if not chess.isGameOver(): if chess._turn == chess.BLACK: curArmy = chess._black_army else: curArmy = chess._white_army if chess._secondTurn: print("{}'s Warrior King turn. Type your move, or type \"decline\" to skip.".format(str(chess.value_to_color_dict[turn]))) else: print("{}'s turn. Type your move.".format(str(chess.value_to_color_dict[turn]))) move = input("> ") # Fully quit the program, regardless. if move == "exit": sys.exit(0) # Save the current game as a pgn file. elif move == "save": f = open('san.pgn', 'w') acc = "" save = chess.getAllTextMoves(chess.SAN) for moves in save: length, w, b = moves if b is None: b = "" acc = acc + "{}. {} {} ".format(length, w, b) pgn_details = prototype pgn_details.append('[Result "' + chess.pgn_result_list[chess.getGameResult()] + '"]') pgn_details.append('') pgn_details.append(acc.rstrip()) for x in pgn_details: f.write(str(x) + '\n') f.close() elif any(var in move for var in ("SAN", "san")): san = chess.getAllTextMoves(chess.SAN) if san: for moves in san: length, x, y = moves print("{}. {} {}".format(length, x, y)) elif any(var in move for var in ("LAN", "lan")): lan = chess.getAllTextMoves(chess.LAN) if lan: for moves in lan: length, x, y = moves print("{}. {} {}".format(length, x, y)) elif any(var in move for var in ("AN", "an")): an = chess.getAllTextMoves(chess.AN) if an: for moves in an: length, x, y = moves print("{}. {} {}".format(length, x, y)) elif any(var in move for var in ("FEN", "fen")): print(chess.getFEN()) elif move == "set": chess.setFEN(input("Paste FEN: ")) elif move == "get": # Displaying available moves for a given space. getter = input("> ") print(str(getter)) try: getter = chess.parseTextMove(getter)[3:5] print(chess.getValidMoves(getter)) except: pass elif len(move) < 2: print("Type a real move.") elif any(var in move for var in ("whirlwind", "ww", "Whirlwind", "WW")): if curArmy == chess.TWOKINGS: print("Which Warrior King performs the whirlwind?") while True: location = input("> ") if location == "exit": sys.exit(0) elif len(location) != 2: print("Please only enter the square.") else: res = chess.addTextMove("K" + location, secondTurn=chess._secondTurn, whirlwind=True) if not res: print("Can't whirlwind there.") turn = chess.getTurn() break else: print("You're not playing Two Kings!") elif any(var in move for var in ("decline", "Decline", "skip", "s", "Skip", "S")): if curArmy == chess.TWOKINGS: if chess._secondTurn: print("Second turn skipped.") chess._secondTurn = False if chess._turn == chess.BLACK: chess._turn = chess.WHITE else: chess._turn = chess.BLACK turn = chess.getTurn() else: print("You're not playing Two Kings!") else: res = chess.checkTextMove(move) # True: a correctly entered move if res is True: result = chess.addTextMove(move, secondTurn=chess._secondTurn) if result: turn = chess.getTurn() chess.updateRoyalLocations() elif chess.getReason() == chess.MUST_SET_PROMOTION: print("{}, what do you want to promote to?".format(chess.value_to_color_dict[turn])) print('Please enter the letter of the piece: QRNB.') while True: promo = input("> ") promo = str(promo.upper()) if len(promo) == 1: if any(var in promo for var in ("Q", "R", "N", "B")): break print('Please enter the letter of the piece: QRNB.') print('Please enter the letter of the piece: QRNB.') result = chess.addTextMove(move+promo, secondTurn=chess._secondTurn) if result: turn = chess.getTurn() chess.updateRoyalLocations() else: print("{}".format(chess.move_reason_list[chess.getReason()])) else: print("{}".format(chess.move_reason_list[chess.getReason()])) # False: The move couldn't be parsed or is ambiguous or wrong elif res is False: print("{}".format(chess.move_reason_list[chess.getReason()])) # Other: TIME TO DU-DU-DU-DUEL else: print("{}, would you like to initiate a duel? It will cost {}.".format(str(chess.value_to_color_dict[not turn]), res)) tmp_white = chess._white_stones tmp_black = chess._black_stones duel_cost = None while True: answer = input("> ") if answer == "exit": sys.exit(0) # Duel initiation elif any(var in answer for var in ('y', 'Y', 'Yes', 'yes')): duel_cost = res if turn == chess.WHITE: tmp_white = tmp_white + res tmp_att = tmp_white tmp_def = tmp_black else: tmp_black = tmp_black + res tmp_att = tmp_black tmp_def = tmp_white print("White stones: {}".format(tmp_white)) print("Black stones: {}".format(tmp_black)) print("{}, how much would you like to bid?".format(str(chess.value_to_color_dict[not turn]))) # Defender Bid while True: defending_bid = getpass.getpass("> ") if defending_bid == "exit": sys.exit(0) elif defending_bid in string.digits: if int(defending_bid) <= min(2, tmp_def): if int(defending_bid) > -1: defending_bid = int(defending_bid) break print("Please only bid a number of stones between 0 and {}.".format(min(2, tmp_def))) print("Please only bid a number of stones between 0 and {}.".format(min(2, tmp_def))) else: print("Please only bid a number of stones between 0 and {}.".format(min(2, tmp_def))) print("{}, how much would you like to bid?".format(str(chess.value_to_color_dict[turn]))) # Attacker Bid while True: attacking_bid = getpass.getpass("> ") if attacking_bid == "exit": sys.exit(0) elif attacking_bid in string.digits: if int(attacking_bid) <= min(2, tmp_att): if int(attacking_bid) > -1: attacking_bid = int(attacking_bid) break print("Please only bid a number of stones between 0 and {}.".format(min(2, tmp_att))) print("Please only bid a number of stones between 0 and {}.".format(min(2, tmp_att))) else: print("Please only bid a number of stones between 0 and {}.".format(min(2, tmp_att))) if attacking_bid == 0 and defending_bid == 0: duel_results = chess.BLUFF elif attacking_bid >= defending_bid: duel_results = chess.ATT_WIN else: duel_results = chess.DEF_WIN # duel_results will now be either 0, 1, or 2 print("{} bid: {}".format(chess.value_to_color_dict[turn], attacking_bid)) print("{} bid: {}".format(chess.value_to_color_dict[not turn], defending_bid)) if duel_results == chess.BLUFF: print("{} called the bluff! Do you want to gain a stone or force {} to lose a stone?".format( chess.value_to_color_dict[turn], chess.value_to_color_dict[not turn])) while True: bluff_choice = input("> ") if bluff_choice == "exit": sys.exit(0) elif any(var in bluff_choice for var in ("g", "gain", "G", "Gain")): att_result = chess.addTextMove(move, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "g") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() break elif chess.getReason() == chess.MUST_SET_PROMOTION: print("{}, what do you want to promote to?".format(chess.value_to_color_dict[turn])) print('Please enter the letter of the piece: QRNB.') while True: promo = input("> ") promo = str(promo.upper()) if len(promo) == 1: if any(var in promo for var in ("Q", "R", "N", "B")): break print('Please enter the letter of the piece: QRNB.') print('Please enter the letter of the piece: QRNB.') att_result = chess.addTextMove(move+promo, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "g") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() else: print("{}".format(chess.move_reason_list[chess.getReason()])) break else: print("{}".format(chess.move_reason_list[chess.getReason()])) break elif any(var in bluff_choice for var in ("l", "lose", "L", "Lose")): att_result = chess.addTextMove(move, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "l") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() break elif chess.getReason() == chess.MUST_SET_PROMOTION: print("{}, what do you want to promote to?".format(chess.value_to_color_dict[turn])) print('Please enter the letter of the piece: QRNB.') while True: promo = input("> ") promo = str(promo.upper()) if len(promo) == 1: if any(var in promo for var in ("Q", "R", "N", "B")): break print('Please enter the letter of the piece: QRNB.') print('Please enter the letter of the piece: QRNB.') att_result = chess.addTextMove(move+promo, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "l") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() else: print("{}".format(chess.move_reason_list[chess.getReason()])) break else: print("{}".format(chess.move_reason_list[chess.getReason()])) break else: print('Please choose between gaining a stone and forcing a lose of a stone.') elif duel_results == chess.ATT_WIN: print("Attacker wins!") att_result = chess.addTextMove(move, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "n") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() elif chess.getReason() == chess.MUST_SET_PROMOTION: print("{}, what do you want to promote to?".format(chess.value_to_color_dict[turn])) print('Please enter the letter of the piece: QRNB.') while True: promo = input("> ") promo = str(promo.upper()) if len(promo) == 1: if any(var in promo for var in ("Q", "R", "N", "B")): break print('Please enter the letter of the piece: QRNB.') print('Please enter the letter of the piece: QRNB.') att_result = chess.addTextMove(move+promo, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "n") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() else: print("{}".format(chess.move_reason_list[chess.getReason()])) else: print("{}".format(chess.move_reason_list[chess.getReason()])) else: print("Defender wins!") att_result = chess.addTextMove(move, secondTurn=chess._secondTurn, clearLocation=True, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "n") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() elif chess.getReason() == chess.MUST_SET_PROMOTION: print("{}, what do you want to promote to?".format(chess.value_to_color_dict[turn])) print('Please enter the letter of the piece: QRNB.') while True: promo = input("> ") promo = str(promo.upper()) if len(promo) == 1: if any(var in promo for var in ("Q", "R", "N", "B")): break print('Please enter the letter of the piece: QRNB.') print('Please enter the letter of the piece: QRNB.') att_result = chess.addTextMove(move+promo, secondTurn=chess._secondTurn, duel=str(duel_cost) + str(attacking_bid) + str(defending_bid) + "n") if att_result: turn = chess.getTurn() chess.updateRoyalLocations() else: print("{}".format(chess.move_reason_list[chess.getReason()])) else: print("{}".format(chess.move_reason_list[chess.getReason()])) turn = chess.getTurn() break # Non-Duel initiation elif any(var in answer for var in ('n', 'N', 'No', 'no')): result = chess.addTextMove(move, secondTurn=chess._secondTurn) if result: turn = chess.getTurn() chess.updateRoyalLocations() elif chess.getReason() == chess.MUST_SET_PROMOTION: print("{}, what do you want to promote to?".format(chess.value_to_color_dict[turn])) print('Please enter the letter of the piece: QRNB.') while True: promo = input("> ") promo = str(promo.upper()) if len(promo) == 1: if any(var in promo for var in ("Q", "R", "N", "B")): break print('Please enter the letter of the piece: QRNB.') print('Please enter the letter of the piece: QRNB.') result = chess.addTextMove(move+promo, secondTurn=chess._secondTurn) if result: turn = chess.getTurn() chess.updateRoyalLocations() else: print("{}".format(chess.move_reason_list[chess.getReason()])) else: print("{}".format(chess.move_reason_list[chess.getReason()])) break else: print('Please enter \'yes\' or \'no\'.') break else: break f = open('san.pgn', 'w') acc = "" save = chess.getAllTextMoves(chess.SAN) for moves in save: length, w, b = moves if b is None: b = "" acc = acc + "{}. {} {} ".format(length, w, b) acc = acc + chess.pgn_result_list[chess.getGameResult()] pgn_details = prototype pgn_details.append('[Result "' + chess.pgn_result_list[chess.getGameResult()] + '"]') pgn_details.append('') pgn_details.append(acc.rstrip()) for x in pgn_details: f.write(str(x) + '\n') f.close() print("Game over! {}".format(chess.game_result_list[chess.getGameResult()]))
def mainLoop(self): pygame.init() print "White Player, choose an army:" print "1. Classic 2. Nemesis 3. Reaper" print "4. Empowered 5. Two Kings 6. Animals" while True: userInput = raw_input('Type the number, not the name:') if userInput in string.digits: if int(userInput) < 7: if int(userInput) > 0: break print 'Please enter only one of the above.' else: print 'Please enter only one character' wArmy = userInput print "Black Player, choose an army:" print "1. Classic 2. Nemesis 3. Reaper" print "4. Empowered 5. Two Kings 6. Animals" while True: userInput = raw_input('Type the number, not the name:') if userInput in string.digits: if int(userInput) < 7: if int(userInput) > 0: break print 'Please enter only one of the above.' else: print 'Please enter only one of the above.' bArmy = userInput pieces = {} chess = ChessBoard(int(wArmy), int(bArmy)) board = chess.getBoard() turn = chess.getTurn() screen = pygame.display.set_mode((840, 480), 1) pygame.display.set_caption('ChessBoard Client') # load all images # pieces format: # pieces[background id: 0 = white, 1 = black]["piece letter"] pieces = [{}, {}] pieces[0]["."] = pygame.image.load("./img/Generic/w.png") pieces[1]["."] = pygame.image.load("./img/Generic/b.png") # file names format: # (army color)(piece letter)(background color).png # white background for img in chess.piece_to_army_dict: for color in chess.color_dict: for back in chess.color_dict: if color == 0: pieces[back][img] = pygame.image.load( "./img/" + chess.piece_to_army_dict[img] + "/" + chess.color_dict[color] + img.lower() + chess.color_dict[back] + ".png") else: img = img.lower() pieces[back][img] = pygame.image.load( "./img/" + chess.piece_to_army_dict[img.upper()] + "/" + chess.color_dict[color] + img + chess.color_dict[back] + ".png") clock = pygame.time.Clock() posRect = pygame.Rect(0, 0, 60, 60) sidebarRect = pygame.Rect(480, 0, 360, 480) mousePos = [-1, -1] markPos = [-1, -1] validMoves = [] pieceSelected = None while 1: clock.tick(30) for event in pygame.event.get(): if event.type == QUIT: return elif event.type == KEYDOWN: if event.key == K_ESCAPE: return elif event.key == K_LEFT: chess.undo() elif event.key == K_RIGHT: chess.redo() elif event.unicode in ("f", "F"): print chess.getFEN() elif event.unicode in ("a", "A"): an = chess.getAllTextMoves(chess.AN) if an: print "AN: " + ", ".join(an) elif event.unicode in ("s", "S"): san = chess.getAllTextMoves(chess.SAN) if san: print "SAN: " + ", ".join(san) elif event.unicode in ("l", "L"): lan = chess.getAllTextMoves(chess.LAN) if lan: print "LAN: " + ", ".join(lan) board = chess.getBoard() turn = chess.getTurn() markPos[0] = -1 validMoves = [] if not chess.isGameOver(): if event.type == MOUSEMOTION: mx = event.pos[0] my = event.pos[1] mousePos[0] = mx / 60 mousePos[1] = my / 60 elif event.type == MOUSEBUTTONDOWN: if mousePos[0] != -1: if markPos[0] == mousePos[0] and markPos[1] == mousePos[1]: markPos[0] = -1 validMoves = [] pieceSelected = None else: if pieceSelected is None: if (turn == ChessBoard.WHITE and board[mousePos[1]][mousePos[0]].isupper()) or \ (turn == ChessBoard.BLACK and board[mousePos[1]][mousePos[0]].islower()): markPos[0] = mousePos[0] markPos[1] = mousePos[1] validMoves = chess.getValidMoves(tuple(markPos)) pieceSelected = board[markPos[1]][markPos[0]].upper elif pieceSelected == ("H" or "E"): if markPos[0] != -1: res = chess.addMove(markPos, mousePos) if not res and chess.getReason() == chess.MUST_SET_PROMOTION: chess.setPromotion(chess.QUEEN) res = chess.addMove(markPos, mousePos) if res: print chess.getLastTextMove(chess.SAN) board = chess.getBoard() turn = chess.getTurn() chess.updateRoyalLocations() markPos[0] = -1 validMoves = [] pieceSelected = None else: if markPos[0] != -1: res = chess.addMove(markPos, mousePos) if not res and chess.getReason() == chess.MUST_SET_PROMOTION: chess.setPromotion(chess.QUEEN) res = chess.addMove(markPos, mousePos) if res: print chess.getLastTextMove(chess.SAN) board = chess.getBoard() turn = chess.getTurn() chess.updateRoyalLocations() markPos[0] = -1 validMoves = [] pieceSelected = None if chess.isGameOver(): pygame.display.set_caption("Game Over! %s" % chess.game_result_dict[chess.getGameResult()]) validMove = [] markPos[0] = -1 markPos[1] = -1 else: pygame.display.set_caption('ChessBoard Client') y = 0 for rank in board: x = 0 for p in rank: screen.blit(pieces[(x + y) % 2][p], (x * 60, y * 60)) x += 1 y += 1 if markPos[0] != -1: posRect.left = markPos[0] * 60 posRect.top = markPos[1] * 60 pygame.draw.rect(screen, (255, 255, 0), posRect, 4) for v in validMoves: posRect.left = v[0] * 60 posRect.top = v[1] * 60 pygame.draw.rect(screen, (255, 255, 0), posRect, 4) pygame.draw.rect(screen, (0, 0, 0), sidebarRect, 0) pygame.display.flip()
class Game: def __init__(self): pygame.init() self.game_display = pygame.display.set_mode((900, 650)) pygame.display.set_caption('Chess') self.settings = {'board_image': 'images/orange_board.png'} self.board_image = pygame.image.load(self.settings['board_image']) self.clock = pygame.time.Clock() self.chess_board = ChessBoard() self.curr_selected_piece = None self.curr_poss_moves = [] self.all_poss_moves = self.get_all_poss_moves() self.white_pieces_taken_images = [] self.black_pieces_taken_images = [] self.play_game() def play_game(self): """Loop that executes the game""" while True: # Draw whole window (and draw board) self.draw_window() for event in pygame.event.get(): if event.type == pygame.QUIT: quit() if event.type == pygame.MOUSEBUTTONUP: # Get user click self.get_user_click() # pygame.display.flip() self.clock.tick(60) def draw_window(self): """Draws everything in the window""" self.game_display.fill(white) # Draw side menu self.draw_side_menu() # Draw bottom menu # Draw board self.draw_board() pygame.display.update() def draw_side_menu(self): """Draws right side menu""" pygame.draw.rect(self.game_display, black, Rect((650, 100), (200, 400)), 5) # Draw box around current player if self.chess_board.curr_player == 'b': pygame.draw.rect(self.game_display, blue, Rect((700, 25), (100, 50)), 5) else: pygame.draw.rect(self.game_display, blue, Rect((700, 525), (100, 50)), 5) self.message_display('Black', (750, 50), fontsize=30) self.message_display('White', (750, 550), fontsize=30) # Display all moves played start = 0 if len(self.get_all_played_moves()) > 10: start = len(self.get_all_played_moves()) - 10 for i, move in enumerate(self.get_all_played_moves()[start:]): self.message_display(move, (740, 125 + (i * 30)), fontsize=20) start += 1 # Display all black pieces taken for i, image in enumerate(self.black_pieces_taken_images): image = pygame.image.load(image) image = pygame.transform.scale(image, (30, 30)) pos = 610 + i * 20, 5 self.game_display.blit(image, pos) # Display all white pieces taken for i, image in enumerate(self.white_pieces_taken_images): image = pygame.image.load(image) image = pygame.transform.scale(image, (30, 30)) pos = 610 + i * 20, 595 self.game_display.blit(image, pos) def draw_board(self): """Draw chess board and all pieces on the board""" # Draw chess board self.game_display.blit(self.board_image, (0, 0)) # Draw pieces on board for piece in self.chess_board.get_all_pieces(): image_position = piece.position image_position = image_position[0] * 75, (7 - image_position[1]) * 75 piece_image = pygame.image.load(piece.image) self.game_display.blit(piece_image, image_position) # Determine if piece is currently selected # If yes: if self.curr_selected_piece: # Highlight that piece box_x, box_y = self.convert_space_to_coordinates(self.curr_selected_piece.position) pygame.draw.rect(self.game_display, blue, Rect((box_x, box_y), (75, 75)), 5) # Display possible moves for that piece for move in self.curr_poss_moves: box1_x, box1_y = self.convert_space_to_coordinates(move) pygame.draw.rect(self.game_display, red, Rect((box1_x, box1_y), (75, 75)), 5) def get_user_click(self): """Analyze the position clicked by the user.""" x, y = pygame.mouse.get_pos() # Determine if click is: # On bottom menu if y > 600: pass # On right side menu elif x > 600: pass # If on board: else: # Convert coordinates into space selected_space = self.convert_coordinates_to_space(x, y) # If piece is not already selected: if not self.curr_selected_piece: # Validate and set curr_selected_piece to this piece if self.is_piece_of_curr_player(selected_space): self.new_piece_selected(selected_space) # Else if piece already selected: else: # Determine if selected space is in possible moves # If space is current selected space if selected_space == self.curr_selected_piece.position: self.deselect_piece() # Else if space in possible moves: elif selected_space in self.curr_poss_moves: #### Check if piece is a king!!! ### # Check if selected space is king and in poss_castle_move if self.curr_selected_piece.name == 'King' and selected_space in self.chess_board.get_castle_moves_for_curr_player(): # Castle that king self.add_move(self.curr_selected_piece.position, selected_space) self.chess_board.castle_king(self.curr_selected_piece, selected_space) else: # Move selected piece to this spot self.add_move(self.curr_selected_piece.position, selected_space) self.move_piece(self.curr_selected_piece, selected_space) if self.curr_selected_piece.name == 'Pawn' and selected_space[1] == 0 or selected_space[1] == 7: self.chess_board.board[selected_space[0]][selected_space[1]] = None self.chess_board.board[selected_space[0]][selected_space[1]] = Queen(self.chess_board.curr_player, selected_space) # Deselect current piece and remove poss moves self.deselect_piece() # Change current player self.change_curr_player() # Check for checkmate and get new list of all possible moves self.all_poss_moves = self.get_all_poss_moves() checkmate = True for piece_pos in self.all_poss_moves: if len(self.all_poss_moves[piece_pos]) != 0: checkmate = False if checkmate: self.draw_window() self.message_display('Checkmate!', (400, 300)) winner = 'White' if self.chess_board.curr_player == 'b' else 'Black' self.message_display('%s wins!' % winner, (400, 400)) pygame.display.update() time.sleep(2) quit() # Else if another piece of curr player: elif selected_space in [piece.position for piece in self.chess_board.get_curr_player_pieces()]: # Make that piece current selected piece self.new_piece_selected(selected_space) # Else (random non-selectable space): else: # Deselect current move self.deselect_piece() def convert_coordinates_to_space(self, x, y): """Converts (x, y) coordinates to corresponding space on board""" # NOTE: Board is drawn upside down, so y axis is flipped return x // 75, 7 - y // 75 def convert_space_to_coordinates(self, position): """Returns the top left corner coordinate corresponding to given chess spot""" return position[0] * 75, (7 - position[1]) * 75 def is_piece_of_curr_player(self, space): """Returns if space holds a piece of current player""" for piece in self.chess_board.get_curr_player_pieces(): if space == piece.position: return True def get_all_poss_moves(self): """Returns dictionary of all possible moves available. NOTE: will return empty list if checkmate""" # Creates dictionary of piece position to possible moves moves = {} pieces = self.chess_board.get_curr_player_pieces() for piece in pieces: p_moves = self.chess_board.get_poss_moves_for(piece) moves[piece.position] = self.chess_board.is_curr_player_in_check(piece, p_moves) return moves def get_curr_poss_moves(self): """Returns possible moves corresponding to cuurently selected piece""" return self.all_poss_moves[self.curr_selected_piece.position] def get_all_played_moves(self): return self.chess_board.played_moves def move_piece(self, piece, new_position): """Moves piece to new position and updates pieces taken""" # NOTE: This just moves piece, does not check if move is valid # Checks if piece is taken piece_captured = self.chess_board.move_piece(piece, new_position) if piece_captured: self.piece_was_captured(piece_captured) def change_curr_player(self): """Change current player between 'w' and 'b'""" self.chess_board.curr_player = 'w' if self.chess_board.curr_player == 'b' else 'b' def new_piece_selected(self, new_space): """Sets new space to curr_selected_piece and gets new moves for that piece""" self.curr_selected_piece = self.chess_board.get_piece_at(new_space) self.curr_poss_moves = self.get_curr_poss_moves() def deselect_piece(self): """Deselects current piece""" self.curr_selected_piece = None self.curr_poss_moves = None def add_move(self, pos_1, pos_2): """Add move to list of played moves""" name = self.chess_board.curr_player.upper() + ': ' move = name + self.convert_coordinate_to_space_name(pos_1) + ' -> ' + self.convert_coordinate_to_space_name(pos_2) self.chess_board.played_moves.append(move) def convert_coordinate_to_space_name(self, coordinate): """Returns converted name of position (ex: (1,3) -> 'B3')""" conversions = {0 : 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H'} return str(conversions[coordinate[0]]) + str(coordinate[1] + 1) def piece_was_captured(self, piece): """Updates list of pieces taken to display on side menu""" if piece.color == 'w': self.white_pieces_taken_images.append(piece.image) else: self.black_pieces_taken_images.append(piece.image) def message_display(self, text, point, fontsize=90): """Displays message in window""" large_text = pygame.font.Font('freesansbold.ttf', fontsize) text_surface = large_text.render(text, True, black) text_rect = text_surface.get_rect() text_rect.center = (point) self.game_display.blit(text_surface, text_rect)
def mainLoop(self): pygame.init() pieces = {} chess = ChessBoard() board = chess.getBoard() turn = chess.getTurn() libro_activo = True libro_overwrite = False board_white = True book=OpeningBook.OpeningBook() letra=pygame.font.Font(None, 40) screen = pygame.display.set_mode((1024, self.tCasilla*8)) pygame.display.set_caption('ChessBoard Client') # load all images pieces = [{},{}] pieces[0]["r"] = pygame.image.load("./img/br.png") pieces[0]["n"] = pygame.image.load("./img/bn.png") pieces[0]["b"] = pygame.image.load("./img/bb.png") pieces[0]["k"] = pygame.image.load("./img/bk.png") pieces[0]["q"] = pygame.image.load("./img/bq.png") pieces[0]["p"] = pygame.image.load("./img/bp.png") pieces[0]["R"] = pygame.image.load("./img/wr.png") pieces[0]["N"] = pygame.image.load("./img/wn.png") pieces[0]["B"] = pygame.image.load("./img/wb.png") pieces[0]["K"] = pygame.image.load("./img/wk.png") pieces[0]["Q"] = pygame.image.load("./img/wq.png") pieces[0]["P"] = pygame.image.load("./img/wp.png") pieces[0]["."] = pygame.image.load("./img/w.png") pieces[1]["r"] = pygame.image.load("./img/br.png") pieces[1]["n"] = pygame.image.load("./img/bn.png") pieces[1]["b"] = pygame.image.load("./img/bb.png") pieces[1]["k"] = pygame.image.load("./img/bk.png") pieces[1]["q"] = pygame.image.load("./img/bq.png") pieces[1]["p"] = pygame.image.load("./img/bp.png") pieces[1]["R"] = pygame.image.load("./img/wr.png") pieces[1]["N"] = pygame.image.load("./img/wn.png") pieces[1]["B"] = pygame.image.load("./img/wb.png") pieces[1]["K"] = pygame.image.load("./img/wk.png") pieces[1]["Q"] = pygame.image.load("./img/wq.png") pieces[1]["P"] = pygame.image.load("./img/wp.png") pieces[1]["."] = pygame.image.load("./img/b.png") clock = pygame.time.Clock() posRect = pygame.Rect(0,0,self.tCasilla,self.tCasilla) rectangulo = pygame.Rect(self.tCasilla*8+5,0,315,self.tCasilla*8) informacion = pygame.Rect(self.tCasilla*8+5,380,315,100) mousePos = [-1,-1] markPos = [-1,-1] validMoves = [] gameResults = ["","WHITE WINS!","BLACK WINS!","STALEMATE","DRAW BY THE FIFTHY MOVES RULE","DRAW BY THE THREE REPETITION RULE"] letra_libro_activo = letra.render("Libro Activo", 1, (255, 255, 255)) letra_libro_overwrite = letra.render("(Sobreescribir)", 1, (255, 255, 255)) while 1: clock.tick(10) # Obtener la pos actual tablero=chess.getFEN() # Escribir el n de jugada num_jugada = str(chess.getCurrentMove()/2 + 1) if turn: num_jugada = num_jugada + ". ..., " else: num_jugada = num_jugada + ". " letra_num_jugada = letra.render(num_jugada, 1, (255, 255, 255)) screen.blit(letra_num_jugada, (self.tCasilla*8+20, 30)) # Obtener las jugadas almacenadas jugadas_teoricas = book.getMoves(tablero) # Si hay jugadas almacenadas, escrcribirlas if jugadas_teoricas != None: num_jugadas = len(jugadas_teoricas) contador = 0 for jugada in jugadas_teoricas: posx = self.tCasilla*8+20 +150*(contador%2) posy = 100 + 40*(contador//2) texto_jugada = letra.render(jugada+jugadas_teoricas[jugada], 1, (255, 255, 255)) screen.blit(texto_jugada, (posx, posy)) contador += 1 # Si libro activo o activada sobreescritura, escribirlo if libro_activo: screen.blit(letra_libro_activo, (self.tCasilla*8+20, 400)) if libro_overwrite: screen.blit(letra_libro_overwrite, (self.tCasilla*8+20, 450)) else: pygame.draw.rect(screen, (0, 0, 0), informacion) # Bucle de eventos for event in pygame.event.get(): if event.type == QUIT: return elif event.type == KEYDOWN: if event.key == K_ESCAPE: # La tecla ESC sale del programa return elif event.key == K_LEFT or event.key == K_o: # La tecla LEFT retrocede una jugada chess.undo() pygame.draw.rect(screen, (0, 0, 0), rectangulo) elif event.key == K_RIGHT or event.key == K_p: # La tecla RIGHT avanza una jugada chess.redo() pygame.draw.rect(screen, (0, 0, 0), rectangulo) elif event.key == K_UP or event.key == K_a: # La tecla UP conmuta entre libro activado y desactivado libro_activo = not libro_activo elif event.key == K_DOWN or event.key == K_s: # La tecla DOWN conmuta el estado de sobreescritura libro_overwrite = not libro_overwrite elif event.unicode in ("f","F"): # La tecla F inprime la pos actual print chess.getFEN() elif event.unicode in ("t","T"): # ? #mykeys = virtkeyboard.VirtualKeyboard() #print mykeys.run(screen, "Nfxh4+") # Invierte el tablero board_white = not board_white elif event.unicode in ("a","A"): # La tecla A imprime la lista de jugadas (AN) an = chess.getAllTextMoves(chess.AN) if an: print "AN: " + ", ".join(an) elif event.unicode in ("s","S"): # La tecla S imprime la lista de jugadas (SAN) san = chess.getAllTextMoves(chess.SAN) if san: print "SAN: " + ", ".join(san) elif event.unicode in ("l","L"): # La tecla L imprime la lista de jugadas (LAN) lan = chess.getAllTextMoves(chess.LAN) if lan: print "LAN: " + ", ".join(lan) board = chess.getBoard() turn = chess.getTurn() markPos[0] = -1 validMoves = [] if not chess.isGameOver(): if event.type == MOUSEMOTION: mx = event.pos[0] my = event.pos[1] mousePos[0] = mx/self.tCasilla mousePos[1] = my/self.tCasilla if not board_white: mousePos[0] = 7 - mousePos[0] mousePos[1] = 7 - mousePos[1] elif event.type == MOUSEBUTTONDOWN: if mousePos[0] >= 0 and mousePos[0] <= 7: if markPos[0] == mousePos[0] and markPos[1] == mousePos[1]: markPos[0] = -1 validMoves = [] else: if (turn==ChessBoard.WHITE and board[mousePos[1]][mousePos[0]].isupper()) or \ (turn==ChessBoard.BLACK and board[mousePos[1]][mousePos[0]].islower()): markPos[0] = mousePos[0] markPos[1] = mousePos[1] validMoves = chess.getValidMoves(tuple(markPos)) else: if markPos[0] != -1: res = chess.addMove(markPos,mousePos) if not res and chess.getReason() == chess.MUST_SET_PROMOTION: chess.setPromotion(chess.QUEEN) res = chess.addMove(markPos,mousePos) if res: jugada = chess.getLastTextMove(chess.SAN) # Almacenar la jugada si es nueva o si activado el modo OVERWRITE if libro_activo: if libro_overwrite or jugadas_teoricas == None or not jugadas_teoricas.has_key(jugada): teclado = virtkeyboard.VirtualKeyboard() valoracion = teclado.run(screen, jugada) book.addMove(tablero, jugada, valoracion,libro_overwrite) board = chess.getBoard() turn = chess.getTurn() markPos[0] = -1 validMoves = [] pygame.draw.rect(screen, (0, 0, 0), rectangulo) if chess.isGameOver(): pygame.display.set_caption("Game Over! (Reason:%s)" % gameResults[chess.getGameResult()]) validMove = [] markPos[0] = -1 markPos[1] = -1 else: pygame.display.set_caption('ChessBoard Client') y = 0 for rank in board: x = 0 for p in rank: screen.blit(pieces[(x+y)%2]["."],(x*self.tCasilla,y*self.tCasilla)) if board_white: screen.blit(pieces[(x+y)%2][p],(x*self.tCasilla,y*self.tCasilla)) else: screen.blit(pieces[(x+y)%2][p],((7-x)*self.tCasilla,(7-y)*self.tCasilla)) x+=1 y+=1 if markPos[0] != -1: if board_white: mP0 = markPos[0] mP1 = markPos[1] else: mP0 = 7 - markPos[0] mP1 = 7 - markPos[1] posRect.left = mP0*self.tCasilla posRect.top = mP1*self.tCasilla pygame.draw.rect(screen, (255,255,0),posRect, 4) for v in validMoves: if board_white: v0 = v[0] v1 = v[1] else: v0 = 7 - v[0] v1 = 7 - v[1] posRect.left = v0*self.tCasilla posRect.top = v1*self.tCasilla pygame.draw.rect(screen, (255,255,0),posRect, 4) pygame.display.flip()
class ChessGame(object): """ A representation of a chess game tracked by an electronic board A ChessGame is able to rebuild a valid game from a sequence of events based on physical squares ! Not thread-safe """ # XXX A move applied by a human must not be able to be undone by automatism # XXX TODO Possibility to associate a change index to a move index by human (all moves before are associated to "human") def __init__(self, x_size, y_size, log=None, initial_position=INITIAL_POSITION, max_pending_moves=MAX_PENDING_MOVES): """ max_pending_moves : * Maximum number of last moves awaiting for mandatory changes before calling for help * Maximum number of moves a non-matched change waits before calling for help """ # FIXME x_size and y_size are not verified against initial_position self.log_function = log or self.defaultLogFunction self.initial_position = initial_position self.max_pending_moves = max_pending_moves self.chessboard = ChessBoard(x_size, y_size) self.chessboard.initializeFEN(initial_position) self.move_history = [] self.change_buffer = [] self.pending_changes = [] self.recording = False self.name = None self.last_ambiguous_change = None initial_repr = initial_position.split("/") initial_repr.reverse() self.change_history = [PhysicalBoardChange(0, None, None, None, initial_repr)] self.change_history_index = 0 def __str__(self): return "Game(%s)" % (self.name or "NoName") def log(self, level, message, *args): """ Logs a message """ self.log_function(self, level, message, *args) def defaultLogFunction(self, obj, level, message, *args): """ Default log function : it simply prints the message on stdout """ print "[%s] - %s - %s" % (obj, level, message % args) def getTurn(self): return self.chessboard.turn def _getPieceColour(self, piece): """ Internal method return the colour of a piece """ if piece in "kqrbnp": return BLACK if piece in "KQRBNP": return WHITE raise Exception("Unknown piece : %s" % piece) def getValidatedDotFEN(self): """ Returns the current validated position in FEN notation with dots in place of spaces """ return self.chessboard.getFEN(dots=True) def getPhysicalDotFEN(self): """ Returns the position on board in FEN notation with dots in place of spaces """ board_repr = self.change_history[self.change_history_index].board_after return_list = [] for i in range(len(board_repr)): return_list.insert(0,"".join(board_repr[i])) return "/".join(return_list) def getPGN(self): """ Returns a PGN representation of the game (without headers) """ return_string = "" for i in range(self.history_index+1): turn = i/2+1 white_turn = i%2 == 0 if white_turn: return_string += " %i." % turn return_string += " " + self.move_list[i]["short"] # XXX use history["last_move"] # XXX 0-1, 1-0 or 1/2-1/2 return return_string.lstrip() def record(self, order): """ Turns on or off recording. order is a boolean """ self.recording = order def update(self, update_type, *args, **kw): """ Updates the current game with given data The parameters depend on the update_type """ f = getattr(self, "_update%s" % update_type.capitalize(), None) if f is not None and callable(f): return f(*args, **kw) raise Exception("Unknown update_type : %s" % update_type) def _updateSquare(self, x, y, new_piece): """ Updates the current game with the given information : The square located on x,y has a new piece """ # change_history[-1] because we append the new change to everything current_repr = self.change_history[-1].board_after current_piece = current_repr[y][x] inserted_change = None if current_piece == new_piece: self.log(VERBOSE, "Piece on %s,%s is already %s - skipping", x, y, new_piece) return if current_piece != "." and new_piece != ".": # Insert a change to free the square inserted_repr = current_repr[:] row = list(inserted_repr[y]) row[x] = "." inserted_repr[y] = "".join(row) inserted_change = PhysicalBoardChange(len(self.change_history), ".", current_piece, Coordinate(x,y), inserted_repr) self.log(VERBOSE, "Receiving from board a change without freeing the square. Inserting a freeing change %s" % inserted_change) self.change_history.append(inserted_change) current_piece = "." new_repr = current_repr[:] row = list(new_repr[y]) row[x] = new_piece new_repr[y] = "".join(row) current_change = PhysicalBoardChange(len(self.change_history), new_piece, current_piece, Coordinate(x,y), new_repr) self.log(VERBOSE, "New change from board : %s", current_change) self.change_history.append(current_change) if self.recording: if inserted_change is not None: self.log(VERBOSE, "Recording is on, handling the inserted change first") self.change_buffer.append(inserted_change) # XXX Only if pending_changes is empty self._handleChange(inserted_change) self.log(VERBOSE, "Recording is on, handling the new change") self.change_buffer.append(current_change) # XXX Only if pending_changes is empty self._handleChange(current_change) # Test if change_buffer is getting too big if len(self.change_buffer) > MAX_BUFFERED_CHANGES: self.log(ERROR, "change_buffer is too big. Undoing last move") undo() raise NeedHelp("Change buffer is too big. Something was wrong. Undid last move") else: if inserted_change is not None: self.log(VERBOSE, "Recording is off, storing the inserted change in pending_changes") self.pending_changes.append(inserted_change) self.log(VERBOSE, "Recording is off, storing the new change in pending_changes") self.pending_changes.append(current_change) def _handleChange(self, current_change): """ Internal method used to treat the content of the change buffer and find associated moves The buffer is populated for each new arriving change while recording is on If recording is off, the buffer is not populated anymore, but another buffer is filled. When recording is set on again, the other buffer empties into change_buffer and each moved change is analyzed here. """ # XXX Manage King positions to indicate game result # Search the change in change_buffer and operate only until it change_buffer = None for i in range(len(self.change_buffer)): if self.change_buffer[i].index == current_change.index: change_buffer = self.change_buffer[:i+1] if change_buffer is None: raise Exception("Change %s is not in change_buffer" % current_change) self.log(VERBOSE, "Handling change %s" % current_change) new_piece = current_change.piece old_piece = current_change.old_piece kw = { "current_change": current_change, "change_buffer" : change_buffer, "new_piece" : new_piece, "old_piece" : old_piece } # First search for a pending symmetrical move (i.e. "square empty" <-> "square gets a piece") if self._searchSymmetricalChange(**kw): return # Search for an awaited change from the previous moves for last_move in self.move_history[-self.max_pending_moves:]: for change in last_move.getAwaitedChanges(): if change == current_change: self.log(VERBOSE, "Found awaited change '%s' from previous move '%s'", current_change, last_move) last_move.associateChange(current_change) last_move.removeAwaitedChange(current_change) removeExactChange(self.change_buffer, current_change) return # Intermediate changes cannot occur after the ending change of a move : # - Promotion is done on the ending square # - Capture is done on the ending square, excepting for en passant, # but in this case the change related to the removed Pawn is mandatory # and registered as an initial move if new_piece == ".": # Look for a previous ambiguous change and try to solve it # with the current change if self._searchUnambiguatingChange(**kw): return self.log(VERBOSE, "Nothing found for change '%s'. Waiting next changes", current_change) return # A landing piece can be the "key" change for a move if self._getPieceColour(new_piece) == self.chessboard.turn: # The previous move was correct and the current player now plays if self._findMove(**kw): return # _findMove always returns True # The landed is of the same colour as the last played move if len(self.move_history)>0 and self.move_history[-1].index > current_change.index: self.log(VERBOSE, "Change %s occurred before Move %s and cannot replace it. Waiting for next changes", current_change, self.move_history[-1]) return if len(self.move_history) == 0: self.log(VERBOSE, "The wrong player plays, but there are no move to undo. Waiting for next changes") return # The opponent player plays again ! # It means the previous identified move was not ended # We need to cancel it and reiterate from the previous validated position self._cancelAndReiterate(**kw) def _searchSymmetricalChange(self, **kw): """ Internal method """ current_change = kw["current_change"] change_buffer = kw["change_buffer"] new_piece = kw["new_piece"] old_piece = kw["old_piece"] symmetrical_change = None for change in change_buffer[:-1]: if symmetrical_change is None: if change.coord == current_change.coord and \ ((new_piece == "." and change.piece == old_piece) or \ (new_piece == change.old_piece and change.piece == ".")): symmetrical_change = change if symmetrical_change is not None: self.log(VERBOSE, "Found symmetrical change '%s' for '%s' : cancelling both", symmetrical_change, current_change) current_change.cancel(symmetrical_change) removeExactChange(self.change_buffer, symmetrical_change) removeExactChange(self.change_buffer, current_change) return True return False def _searchUnambiguatingChange(self, **kw): """ Internal method """ current_change = kw["current_change"] ambiguous_change = self.last_ambiguous_change if ambiguous_change is None: return False # Try to associate this starting change with previous ambiguous one index = findExactChange(self.change_buffer, ambiguous_change) if index is not None and index < current_change.index: self.log(VERBOSE, "Trying to move the currently handled change %s to index %s of change_buffer to resolve ambiguous change %s", current_change, index, ambiguous_change) removeExactChange(self.change_buffer, current_change) self.change_buffer.insert(index, current_change) self._handleChange(ambiguous_change) if findExactChange(self.change_buffer, current_change) is None: self.log(VERBOSE, "Change %s resolved previous ambiguous change %s !", current_change, ambiguous_change) return True else: self.log(VERBOSE, "Change %s did not resold ambiguous change. Resorting change_buffer", current_change) self.change_buffer.sort(key=lambda c: c.index) return False def _findMove(self, **kw): """ Internal method """ current_change = kw["current_change"] change_buffer = kw["change_buffer"] candidate_list = CandidateMoves(self.chessboard).getCandidates(current_change) if len(candidate_list) == 0: self.log(VERBOSE, "No candidate move for change '%s'. Waiting next changes", current_change) return True if len(candidate_list) > 1: # There are more than one possible candidate. # We search for corresponding initial changes self.log(VERBOSE, "Candidate moves for change '%s' : %s. Searching initial changes", current_change, ";".join([str(m) for m in candidate_list])) new_candidate_list = [] for candidate in candidate_list: if len([c for c in change_buffer[:-1] if c in candidate.initial_changes]) > 0: new_candidate_list.append(candidate) if len(new_candidate_list) == 0: self.log(VERBOSE, "No potential initial change found. Waiting next changes") self.last_ambiguous_change = current_change return True if len(new_candidate_list) > 1: self.log(VERBOSE, "Moves found for '%s' : %s. Need human help", current_change, ";".join([str(m) for m in new_candidate_list])) raise NeedHelp("Moves found for '%s' : %s" % (current_change, ";".join([str(m) for m in new_candidate_list]))) # Found a single move, so apply it self.log(VERBOSE, "Move selected for '%s' : %s. Applying", current_change, new_candidate_list[0]) self._applyMove(new_candidate_list[0], current_change.index) return True # Change not ambiguous self.log(VERBOSE, "Only move found for '%s' : %s. Applying", current_change, candidate_list[0]) self._applyMove(candidate_list[0], current_change.index) return True def _cancelAndReiterate(self, **kw): """ Internal method """ current_change = kw["current_change"] self.log(VERBOSE, "The same player plays again. It means the latest move was wrong. Undoing it") self.undo() self.record(True) self.log(INFO, "Last move was undone because the same player has played again. Restarting _handleBuffer") self._handleChange(current_change) if current_change in self.change_buffer: self.log(VERBOSE, "We did an undo for %s, but could not determine a move. Rehandling all changes in change_buffer", current_change) else: self.log(VERBOSE, "%s needed an undo to be interpreted, rehandling all changes in change_buffer", current_change) for change in self.change_buffer[:]: # We work on a copy if change in self.change_buffer and change.index < current_change.index: self._handleChange(change) self.log(VERBOSE, "Rehandled all changes in change_buffer. End of handling for %s", current_change) def _applyMove(self, move, index): """ Apply the given move, associate changes with it, and record the move in ChessBoard """ # In this method we do some sanity checks to avoid strange behaviours # Do not hesitate to call for human help : players are human, then can do anything ! self.log(INFO, "Applying move %s...", move) # Search the change in change_buffer and operate only until it change_buffer = None for i in range(len(self.change_buffer)): if self.change_buffer[i].index == index: change_buffer = self.change_buffer[:i+1] if change_buffer is None: raise Exception("Change index %s is not in change_buffer" % index) # First verify if there are no changes waiting for a while try: old_move = self.move_history[-self.max_pending_moves] awaited_changes = old_move.getAwaitedChanges() if len(awaited_changes) > 0: self.log(ERROR, "Still waiting changes '%s' for move '%s'. Something is wrong", ";".join([str(c) for c in awaited_changes]), old_move) for i in range(self.max_pending_moves): self.undo() raise NeedHelp("Still waiting changes '%s' for move '%s'. Undid %s last moves " % ( ";".join([str(c) for c in awaited_changes]), old_move, self.max_pending_moves)) except IndexError: # Simply no old moves old_move = None # Apply the move itself and associate it with changes move.setIndex(index) self.chessboard.makeMove(move.short_notation) awaited_changes = set(move.initial_changes) | set(move.final_changes) intermediate_changes = set(move.intermediate_changes) for change in change_buffer: if change in awaited_changes: self.log(VERBOSE, "Consuming mandatory change %s", change) awaited_changes.remove(change) move.associateChange(change) removeExactChange(self.change_buffer, change) elif change in intermediate_changes: self.log(VERBOSE, "Consuming intermediate change %s", change) move.associateChange(change) removeExactChange(self.change_buffer, change) else: self.log(VERBOSE, "Change %s is independent from move %s", change, move) self.log(VERBOSE, "Still awaited changes after consuming existing ones : %s", ";".join([str(c) for c in awaited_changes])) move.setAwaitedChanges(*awaited_changes) self.move_history.append(move) # Finally check if some changes in buffer are too old for change in self.change_buffer: change.age += 1 if change.age >= self.max_pending_moves: self.log(ERROR, "Change '%s' is too old. Something is wrong", change) for i in range(self.max_pending_moves): self.undo() raise NeedHelp("Change '%s' is too old. Something is wrong. " % (change) + "Undid %s last moves" % self.max_pending_moves) def undo(self): """ Undo the last move, replace the associated changes in the buffer, and stop the recording to wait a human intervention """ if len(self.move_history) == 0: # XXX exception ? return self.record(False) last_move = self.move_history.pop() for change in self.change_buffer: change.age -= 1 self.log(INFO, "Undoing move %s", last_move) unassociated_changes = last_move.associated_changes index = last_move.index for change in unassociated_changes: self.log(VERBOSE, "Unassociating change %s", change) change.unassociate() #if change.index > index: # self.log(VERBOSE, "Change %s is placed in pending_changes", change) # self.pending_changes.append(change) #else: self.log(VERBOSE, "Change %s is placed in change_buffer", change) self.change_buffer.append(change) #for change in self.change_buffer[:]: # if change.index > index: # self.log(VERBOSE, "Moving change %s from change_buffer to pending_change", change) # self.pending_changes.append(change) # self.change_buffer.remove(change) #self.pending_changes.sort(key=lambda c: c.index) self.change_buffer.sort(key=lambda c: c.index) self.chessboard.undo() self.log(INFO, "Move %s is undone", last_move)
class UserInterface: ROTATIONS_RIGHT = 2 STATE_WAITING_FOR_START_POS = 0 STATE_WAITING_FOR_BOARD_CHANGE = 1 STATE_WAITING_FOR_ENGINE = 2 STATE_GAME_OVER = 3 def __init__(self): self.state = UserInterface.STATE_WAITING_FOR_START_POS self.engine = ChessEngine() self.startingPos = np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 1, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8) if sys.platform == 'darwin': self.cv = MockCV() UserInterface.ROTATIONS_RIGHT = 0 else: self.cv = ChessCV() self.cv.continuous = True thread.start_new_thread(self.cvThread, (self,)) self.boardscan = np.ndarray(shape=(8,8), dtype=np.int8) self.boardscan.fill(0) self.chess = None self.lastFullScreenToggle = 0 self.boardScale = 2 self.considering = [] self.lastConsider = None self.requestedMove = None self.dirtyUi = True pygame.init() #self.screen = pygame.display.set_mode((800, 800)) #self.screen = pygame.display.set_mode((1824, 1016)) self.screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN) self.bgimage = pygame.image.load("./img/background.png") self.light_sabers = pygame.image.load("./img/light_sabers2.png") self.would_you_like_to_play = pygame.image.load("./img/headings/would_you_like_to_play.png") self.checkmate_suckah = pygame.image.load("./img/headings/checkmate_suckah.png") self.my_turn = pygame.image.load("./img/headings/my_turn.png") self.my_turn_move_piece = pygame.image.load("./img/headings/my_turn_move_piece.png") self.one_moment_please = pygame.image.load("./img/headings/one_moment_please.png") self.would_you_like_to_play = pygame.image.load("./img/headings/would_you_like_to_play.png") self.your_turn = pygame.image.load("./img/headings/your_turn.png") self.your_turn_cheater = pygame.image.load("./img/headings/your_turn_cheater.png") self.check = pygame.image.load("./img/bottom_headers/check.png") self.checkmate_suckah = pygame.image.load("./img/bottom_headers/checkmate_suckah.png") self.topHeading = None self.bottomHeading = None self.boardbg = self.loadImage("board_v2.gif") self.pieces = {} self.pieces['r'] = self.loadImage("br.png") self.pieces['n'] = self.loadImage("bn.png") self.pieces['b'] = self.loadImage("bb.png") self.pieces['k'] = self.loadImage("bk.png") self.pieces['q'] = self.loadImage("bq.png") self.pieces['p'] = self.loadImage("bp.png") self.pieces['R'] = self.loadImage("wr.png") self.pieces['N'] = self.loadImage("wn.png") self.pieces['B'] = self.loadImage("wb.png") self.pieces['K'] = self.loadImage("wk.png") self.pieces['Q'] = self.loadImage("wq.png") self.pieces['P'] = self.loadImage("wp.png") pygame.display.flip() def loadImage(self, file): img = pygame.image.load("./img/%s" % file).convert(32, pygame.SRCALPHA) rect = img.get_rect() return pygame.transform.smoothscale(img, (int(rect.w * self.boardScale), int(rect.h * self.boardScale))) def getFont(self, size): return pygame.font.SysFont("freesans", size, bold=True) def mainLoop(self): clock = pygame.time.Clock() self.renderBoard() while 1: clock.tick(30) for event in pygame.event.get(): if event.type == QUIT: return elif event.type == KEYDOWN: print event.key if event.key == K_ESCAPE: return if event.key == 102: # F if time.time() - self.lastFullScreenToggle > 1: self.lastFullScreenToggle = time.time() pygame.display.toggle_fullscreen() if event.key == 32: # space self.cv.snapshot = True if event.key == 49: # 1 self.cv.set_board(self.startingPos.copy()) if event.key == 50: # 2 self.cv.set_board(np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 1, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 0, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8)) if event.key == 51: # 3 self.cv.set_board(np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1, 0,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0,-1, 0, 0, 0, 0], [ 0, 0, 0, 0, 1, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 0, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8)) if event.key == 52: # 4 self.cv.set_board(np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1, 0,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 1, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 0, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8)) self.gameTick() def gameTick(self): self.updateConsideringLine() if self.state == UserInterface.STATE_WAITING_FOR_START_POS: if np.array_equal(self.boardscan, self.startingPos): print "NEW GAME: Creating chess board" self.chess = ChessBoard() self.lastBoardscan = self.boardscan self.engine.newGame() self.topHeading = self.your_turn self.dirtyUi = True self.state = UserInterface.STATE_WAITING_FOR_BOARD_CHANGE elif self.state == UserInterface.STATE_WAITING_FOR_ENGINE: if self.engine.bestmove is not None: self.requestedMove = self.engine.bestmove self.considering = [] self.state = UserInterface.STATE_WAITING_FOR_BOARD_CHANGE self.topHeading = self.my_turn_move_piece self.dirtyUi = True self.renderBoard() elif self.state == UserInterface.STATE_WAITING_FOR_BOARD_CHANGE: changes = self.boardscan - self.lastBoardscan numChanges = np.count_nonzero(changes) if numChanges == 2 or numChanges == 3 or numChanges == 4: self.dirtyUi = True print "" print "changes:\n" + str(changes) moveFrom = () moveTo = () nonzeroChanges = changes.nonzero() print "nonzeroChanges: " + str(nonzeroChanges) print "len(nonzeroChanges[0]) = %d" % len(nonzeroChanges[0]) for i in range(len(nonzeroChanges[0])): change = (nonzeroChanges[1][i], nonzeroChanges[0][i]) value = changes[change[1], change[0]] colorBefore = self.lastBoardscan[change[1], change[0]] print "\tchange: %s\tvalue: %s\tcolorBefore: %s" % (str(change), value, colorBefore) if self.chess.getTurn() == ChessBoard.WHITE: # WHITE's turn if value == -1: if numChanges != 4 or (change == (4,7)): moveFrom = change else: if numChanges == 4: if change == (6,7) or change == (2,7): moveTo = change elif numChanges == 3: if colorBefore == 0: moveTo = change else: moveTo = change else: # BLACK's turn if value == 1: if numChanges != 4 or (change == (4,0)): print "setting moveFrom to ", change moveFrom = change else: if numChanges == 4: if change == (6,0) or change == (2,0): print "setting moveTo to ", change moveTo = change elif numChanges == 3: if colorBefore == 0: print "setting moveTo to ", change moveTo = change else: moveTo = change print "moveFrom: " + str(moveFrom) print "moveTo: " + str(moveTo) if moveFrom and moveTo: print "getTurn before:", self.chess.getTurn() result = self.chess.addMove(moveFrom, moveTo) print "getTurn after:", self.chess.getTurn() if result is False: print "Could not make move: ", self.chess.getReason() else: lastMove = string.replace(self.chess.getLastTextMove(ChessBoard.AN), '-', '') cheater = False if self.requestedMove is not None and self.requestedMove != lastMove: cheater = True if self.chess.isCheck(): print "**** CHECK ****" self.bottomHeading = self.check else: self.bottomHeading = None self.requestedMove = None self.lastBoardscan = self.boardscan self.chess.printBoard() print "Last move type: " + str(self.chess.getLastMoveType()) print "New FEN: " + self.chess.getFEN() # Check if game is over if self.chess.isGameOver(): result = self.chess.getGameResult() if result == ChessBoard.WHITE_WIN: print "**** WHITE WINS ****" elif result == ChessBoard.BLACK_WIN: print "**** BLACK WINS ****" self.bottomHeading = self.checkmate_suckah else: print "**** STALEMATE ****" self.state = UserInterface.STATE_GAME_OVER elif self.chess.getTurn() == ChessBoard.BLACK: # It's black's turn, engage the engine self.topHeading = self.one_moment_please self.engine.makeMove(self.chess.getFEN()) self.state = UserInterface.STATE_WAITING_FOR_ENGINE else: if cheater: self.topHeading = self.your_turn_cheater else: self.topHeading = self.your_turn self.renderBoard() elif numChanges != 0: print "Invalid number of board changes: ", numChanges self.cv.reset_board() # Set boardscan to the last one just so we don't keep analyzing it until next scan comes in self.boardscan = self.lastBoardscan self.renderBoard() def updateConsideringLine(self): now = time.time() engine_considering = self.engine.considering if self.state == UserInterface.STATE_WAITING_FOR_ENGINE and engine_considering is not None: if len(self.engine.considering) > 0: latest = engine_considering[0] if len(latest) == 0: engine_considering.pop() self.considering = [] self.updateConsideringLine() return self.considering.append(latest.pop()) self.lastConsider = now self.dirtyUi = True self.renderBoard() def renderBoard(self): if not self.dirtyUi: return self.dirtyUi = False self.screen.blit(self.bgimage, (0,0)) if self.chess is None: self.screen.blit(self.would_you_like_to_play, (587, 395)) pygame.display.flip() return files = 'abcdefgh' boardOffsetX = 64 boardOffsetY = 64 square_size = self.pieces['r'].get_rect().w # First the background bgsize = self.boardbg.get_rect().w for y in range(4): for x in range(4): self.screen.blit(self.boardbg, (boardOffsetX+x*bgsize, boardOffsetY+y*bgsize)) # Render the pieces y = 0 for rank in self.chess.getBoard(): x = 0 for p in rank: if p != '.': self.screen.blit(self.pieces[p],(boardOffsetX+x*square_size, boardOffsetY+y*square_size)) x += 1 y += 1 # Heading if self.topHeading is not None: self.screen.blit(self.topHeading, (1105, 84)) # Sabers self.screen.blit(self.light_sabers, (1105, 84 + 140)) # Render considering moves (if any) if len(self.considering) > 0: for move in self.considering: x1 = boardOffsetX+files.find(move[0])*square_size+int(square_size/2) y1 = boardOffsetY+((8-int(move[1]))*square_size)+int(square_size/2) x2 = boardOffsetX+files.find(move[2])*square_size+int(square_size/2) y2 = boardOffsetY+((8-int(move[3]))*square_size)+int(square_size/2) pygame.draw.line(self.screen, (164, 119, 131), (x1,y1), (x2,y2), 15) pygame.draw.circle(self.screen, (127, 91, 102), (x1,y1), 15) pygame.draw.circle(self.screen, (127, 91, 102), (x2,y2), 15) # Render requested move (if any) if self.requestedMove is not None: x1 = boardOffsetX+files.find(self.requestedMove[0])*square_size+int(square_size/2) y1 = boardOffsetY+((8-int(self.requestedMove[1]))*square_size)+int(square_size/2) x2 = boardOffsetX+files.find(self.requestedMove[2])*square_size+int(square_size/2) y2 = boardOffsetY+((8-int(self.requestedMove[3]))*square_size)+int(square_size/2) pygame.draw.line(self.screen, (229, 72, 84), (x1,y1), (x2,y2), 15) pygame.draw.circle(self.screen, (173, 58, 75), (x2,y2), 15) # Redraw piece on "from" square so line comes from underneath it (but covers other pieces, potentially) y = 8-int(self.requestedMove[1]) x = files.find(self.requestedMove[0]) piece = self.chess.getBoard()[y][x] self.screen.blit(self.pieces[piece],(boardOffsetX+x*square_size, boardOffsetY+y*square_size)) # Bottom heading if self.bottomHeading is not None: self.screen.blit(self.bottomHeading, (1105, 84 + 140 + 165 + 403)) # Render chess moves color = (255, 255, 255) x = 1105 startY = 84 + 140 + 165 y = startY font = self.getFont(20) allMoves = self.chess.getAllTextMoves(ChessBoard.LAN) if allMoves is not None: whiteMoves = allMoves[0::2] blackMoves = allMoves[1::2] num = 1 for move in whiteMoves: txt = "%d. %s" % (num, move) if num < 10: txt = " " + txt fs = font.render(txt, True, color) self.screen.blit(fs, (x, y)) y += 25 num = num + 1 if y > startY + 403: break x += 200 y = startY for move in blackMoves: fs = font.render(move, True, color) self.screen.blit(fs, (x, y)) y += 25 if y > startY + 403: break pygame.display.flip() def cvThread(self, cv): while True: try: if self.state == UserInterface.STATE_WAITING_FOR_BOARD_CHANGE or self.state == UserInterface.STATE_WAITING_FOR_START_POS: if self.cv.continuous == True or self.cv.snapshot == True: self.cv.snapshot = False sys.stdout.write('.') sys.stdout.flush() board = self.cv.current_board() if board is not None: self.boardscan = np.rot90(board, UserInterface.ROTATIONS_RIGHT) except Exception, e: print e time.sleep(0.25)
#!/usr/bin/python # Hello World from Python from ChessBoard import ChessBoard def solveBoard(board): if(board.isSolved()): return True else: curr_Pos = board.curr_Pos() moves = board.nextMove() for move in moves: x = move[0] y = move[1] board.add_Move(x, y) if(solveBoard(board)): return True else: board.remove_Last() #print "Reversing" return False for i in xrange(8): x = ChessBoard() x.add_Move(i, 0) solveBoard(x) #next = x.nextMove() #print next x.printGrid() print " "
class ChessGame: def __init__(self, player_white, player_black): self.board = ChessBoard() self.board.set_start_position() self.player_white = player_white self.player_black = player_black self.move_number = 1 self.previous_board = copy.deepcopy(self.board) self.result_notation_text = '' self.is_white_check = False self.is_black_check = False self.possible_white_long_castling = True self.possible_white_short_castling = True self.possible_black_long_castling = True self.possible_black_short_castling = True # self.move_correct_checkers = {ChessPieceType.Pawn: self.is_pawn_move_correct, # ChessPieceType.Rook: self.is_rook_move_correct, # ChessPieceType.Bishop: self.is_bishop_move_correct, # ChessPieceType.Queen: self.is_queen_move_is_correct, # ChessPieceType.King: self.is_king_move_correct, # ChessPieceType.Knight: self.is_knight_move_correct} def can_this_color_fix_check(self, color): if self.whose_turn() != color: return False for i in range(BOARD_SIZE): for j in range(BOARD_SIZE): if not self.board.is_empty(i, j): if self.board.get_piece(i, j).get_color() == color: for k in range(BOARD_SIZE): for l in range(BOARD_SIZE): if self.is_move_correct(i, j, k, l): attacked_piece = None if not self.board.is_empty(k, l): attacked_piece = self.board.get_piece(k, l) self.board.move_piece(i, j, k, l) if not self.is_check(color): self.board.move_piece(k, l, i, j) self.board.set_piece(k, l, attacked_piece) return True self.board.move_piece(k, l, i, j) self.board.set_piece(k, l, attacked_piece) return False def move(self, source_x, source_y, destination_x, destination_y): if self.board.is_empty(source_x, source_y): raise ChessException('Empty source square') source_color = self.board.get_piece(source_x, source_y).get_color() if self.whose_turn() != source_color: raise ChessException("It's "+str(source_color.get_another_color())+' turn!') if not self.is_move_correct(source_x, source_y, destination_x, destination_y): raise ChessException("Incorrect move") # Если это рокировка, то ладью тоже нужно передвинуть #self.previous_board = copy.deepcopy(self.board) if self.check_castling(source_x, source_y, destination_x, destination_y): if destination_x < source_x: rook_x = 0 else: rook_x = BOARD_SIZE - 1 # destination_x может быть равна только 3 или 5 self.add_step_to_notation_if_castling(source_x, source_y, destination_x, destination_y) self.board.move_piece(rook_x, source_y, 3 + 2 * sign(rook_x), source_y) else: self.add_step_to_notation(source_x, source_y, destination_x, destination_y) self.board.move_piece(source_x, source_y, destination_x, destination_y) self.move_number += 1 black_mate = self.is_mate(ChessColor.Black) white_mate = self.is_mate(ChessColor.White) if black_mate or white_mate: self.result_notation_text += '#' # Если ход был сделан Ладьей или Королем, исключаем дальнейшую возможность соответствующих рокировок if (source_x, source_y) == (0, 0) or (source_x, source_y) == (4, 0) or (destination_x, destination_y) == (0, 0): self.possible_white_long_castling = False if (source_x, source_y) == (7, 0) or (source_x, source_y) == (4, 0) or (destination_x, destination_y) == (7, 0): self.possible_white_short_castling = False if (source_x, source_y) == (0, 7) or (source_x, source_y) == (4, 7) or (destination_x, destination_y) == (0, 7): self.possible_black_long_castling = False if (source_x, source_y) == (7, 7) or (source_x, source_y) == (4, 7) or (destination_x, destination_y) == (7, 7): self.possible_black_short_castling = False if self.is_check(ChessColor.Black): self.is_black_check = True elif self.is_black_check: self.is_black_check = False if self.is_check(ChessColor.White): self.is_white_check = True elif self.is_white_check: self.is_white_check = False #print(self.squares_changed_last_move()) def squares_changed_last_move(self): result = [] for i in range(BOARD_SIZE): for j in range(BOARD_SIZE): if self.board.is_empty(i, j) + self.previous_board.is_empty(i, j) == 1: result.append((i, j)) #print(i, j) elif self.board.is_empty(i, j) + self.previous_board.is_empty(i, j) == 0: if self.board.get_piece(i, j) != self.previous_board.get_piece(i, j): result.append((i, j)) #print(self.previous_board.get_piece(i, j), self.board.get_piece(i, j)) #print(result) return result def whose_turn(self): if self.move_number % 2 == 0: return ChessColor.Black return ChessColor.White def is_check(self, color): # print(type(self.board.find_king(color))) # self.board.show() (king_x, king_y) = self.board.find_king(color) # print('looking for ', str(color), 'King === ', king_x,' ', king_y) return self.can_be_attacked(king_x, king_y, color) def is_mate(self, color): return self.is_check(color) and not self.can_this_color_fix_check(color) def make_check_himself(self, source_x, source_y, destination_x, destination_y): color = self.board.get_piece(source_x, source_y).get_color() self.board.move_piece(source_x, source_y, destination_x, destination_y) if self.is_check(color): self.board.move_piece(destination_x, destination_y, source_x, source_y) return True self.board.move_piece(destination_x, destination_y, source_x, source_y) return False # Проверяет, что # в клетке [source] есть фигура # если в клетке [destination] есть фигура, то она другого цвета # check_is_move_under_check - проверить, есть ли сейчас шах ходящему игроку, и, если есть, корректен ли ход с точки зрения этого шаха # (закрывает ли его при необходимости) def is_move_correct(self, source_x, source_y, destination_x, destination_y, check_is_move_under_check=True): if self.board.is_empty(source_x, source_y): return False source_color = self.board.get_piece(source_x, source_y).get_color() if not self.board.is_empty(destination_x, destination_y): destination_color = self.board.get_piece(destination_x, destination_y).get_color() if source_color == destination_color: return False piece_type = self.board.get_piece(source_x, source_y).get_type() # Check the castling if self.check_castling(source_x, source_y, destination_x, destination_y): return True # if self.make_check_himself(source_x, source_y, destination_x, destination_y): # return False if check_is_move_under_check: if self.is_check(source_color): piece_under_attack = None if not self.board.is_empty(destination_x, destination_y): piece_under_attack = self.board.get_piece(destination_x, destination_y) self.board.move_piece(source_x, source_y, destination_x, destination_y) is_check_after_move = self.is_check(source_color) self.board.move_piece(destination_x, destination_y, source_x, source_y) self.board.set_piece(destination_x, destination_y, piece_under_attack) if is_check_after_move: return False return move_correct_checkers[piece_type](self, source_x, source_y, destination_x, destination_y) def can_be_attacked(self, x, y, color): result = False substitution_done = False if self.board.is_empty(x, y): self.board.set_piece(x, y, ChessPiece(color, ChessPieceType.Pawn)) substitution_done = True for i in range(BOARD_SIZE): for j in range(BOARD_SIZE): if self.is_move_correct(i, j, x, y, check_is_move_under_check=False): result = True if substitution_done: self.board.clear_square(x, y) return result def check_castling(self, source_x, source_y, destination_x, destination_y): if self.board.is_empty(source_x, source_y): return False if self.board.get_piece(source_x, source_y).get_type() != ChessPieceType.King: return False difference_x = destination_x - source_x difference_y = destination_y - source_y if abs(difference_x) != 2 or difference_y != 0: return False factor_x = sign(difference_x) # Проверям, что на пути от короля до ладьи ничего не стоит checking_square = [source_x + factor_x, source_y] while self.board.is_empty(*checking_square) and 0 <= checking_square[0] < BOARD_SIZE: checking_square[0] += factor_x if checking_square[0] < 0 or checking_square[0] >= BOARD_SIZE: return False if self.board.get_piece(*checking_square).get_type() != ChessPieceType.Rook: return False # Проверка, что король не под шахом и поле, пересекаемое или занимаемое им, не атаковано for i in range(3): checking_square = [source_x + factor_x * i, source_y] if self.can_be_attacked(checking_square[0], checking_square[1], self.board.get_piece(source_x, source_y).get_color()): return False # Проверяем, что данные ладья и король не делали свой ход if (source_x, source_y, destination_x, destination_y) == (4, 0, 2, 0) and self.possible_white_long_castling: return True if (source_x, source_y, destination_x, destination_y) == (4, 0, 6, 0) and self.possible_white_short_castling: return True if (source_x, source_y, destination_x, destination_y) == (4, 7, 2, 7) and self.possible_black_long_castling: return True if (source_x, source_y, destination_x, destination_y) == (4, 7, 6, 7) and self.possible_black_short_castling: return True return False def is_pawn_move_correct(self, source_x, source_y, destination_x, destination_y): pawn = self.board.get_piece(source_x, source_y) color_pawn = pawn.get_color() if source_x == destination_x and self.board.is_empty(destination_x, destination_y): if (source_y - destination_y == 1) and (color_pawn == ChessColor.Black): return True if (destination_y - source_y == 1) and (color_pawn == ChessColor.White): return True if (source_y - destination_y == 2) and (color_pawn == ChessColor.Black) and ( source_y == 6) and self.board.is_empty(source_x, source_y - 1): return True if (destination_y - source_y == 2) and (color_pawn == ChessColor.White) and ( source_y == 1) and self.board.is_empty(source_x, source_y + 1): return True if abs(source_x - destination_x) == 1: if not self.board.is_empty(destination_x, destination_y): color_attacked_piece = self.board.get_piece(destination_x, destination_y).get_color() if (source_y - destination_y == 1) and (color_pawn == ChessColor.Black) and ( color_attacked_piece != color_pawn): return True if (destination_y - source_y == 1) and (color_pawn == ChessColor.White) and ( color_attacked_piece != color_pawn): return True return False def is_knight_move_correct(self, source_x, source_y, destination_x, destination_y): # Knight should move 1 step along the first axis and two steps for the other. 1*2 = 2 if abs(destination_x - source_x) * abs(destination_y - source_y) == 2: if self.board.is_empty(destination_x, destination_y): return True # if the delivery square is not empty, the figure of a different color should be there color_attacking_piece = self.board.get_piece(destination_x, destination_y).get_color() color_attacked_piece = self.board.get_piece(source_x, source_y).get_color() return color_attacked_piece != color_attacking_piece return False def is_rook_move_correct(self, source_x, source_y, destination_x, destination_y): # Проверим, что в пункте назначения не стоит фигура того же цвета, что и наша if not self.board.is_empty(destination_x, destination_y): if self.board.get_piece(source_x, source_y).get_color() == self.board.get_piece(destination_x, destination_y).get_color(): return False difference_x = destination_x - source_x # перемещение вдоль оси Х difference_y = destination_y - source_y # перемещение вдоль оси Y # Если движение не по одной оси, ладья не может сходить так if (difference_x * difference_y != 0) or (difference_x + difference_y == 0): return False # направление по осям factor_x = sign(difference_x) factor_y = sign(difference_y) for index in range(1, abs(difference_x)): if not self.board.is_empty(source_x + factor_x * index, source_y + factor_y * index): return False for index in range(1, abs(difference_y)): if not self.board.is_empty(source_x + factor_x * index, source_y + factor_y * index): return False return True def is_king_move_correct(self, source_x, source_y, destination_x, destination_y): # Проверим, что в пункте назначения не стоит фигура того же цвета, что и наша if not self.board.is_empty(destination_x, destination_y): if self.board.get_piece(source_x, source_y).get_color() == self.board.get_piece(destination_x, destination_y).get_color(): return False difference_x = destination_x - source_x # перемещение вдоль оси Х difference_y = destination_y - source_y # перемещение вдоль оси Y if abs(difference_x) <= 1 and abs(difference_y) <= 1: return True return False def is_bishop_move_correct(self, source_x, source_y, destination_x, destination_y): # Проверим, что в пункте назначения не стоит фигура того же цвета, что и наша if not self.board.is_empty(destination_x, destination_y): if self.board.get_piece(source_x, source_y).get_color() == self.board.get_piece(destination_x, destination_y).get_color(): return False difference_x = destination_x - source_x # перемещение вдоль оси Х difference_y = destination_y - source_y # перемещение вдоль оси Y if abs(destination_x - source_x) != abs(destination_y - source_y): return False # направление по осям factor_x = sign(difference_x) factor_y = sign(difference_y) for index in range(1, abs(difference_x)): if not self.board.is_empty(source_x + factor_x * index, source_y + factor_y * index): return False return True def is_queen_move_is_correct(self, source_x, source_y, destination_x, destination_y): return self.is_bishop_move_correct(source_x, source_y, destination_x, destination_y) or \ self.is_rook_move_correct(source_x, source_y, destination_x, destination_y) def get_number_of_string_in_notation(self): return str((self.move_number+1)//2) + '. ' def add_step_to_notation(self, source_x, source_y, destination_x, destination_y): moving_piece = self.board.get_piece(source_x, source_y) if moving_piece.get_color() == ChessColor.White: # str_step = '\n'*sign(self.game.move_number-1) + str((self.game.move_number+1)//2) + '. ' # str_step = ('\n' if self.game.move_number > 1 else '' ) + str((self.game.move_number+1)//2) + '. ' str_step = ('\n' if self.move_number > 1 else '') + self.get_number_of_string_in_notation() else: str_step = ' ' str_step += moving_piece.get_name_for_notation() str_step += LETTERS_ON_BOARD[source_x] + str(source_y+1) if self.board.is_empty(destination_x, destination_y): str_step += '-' else: str_step += 'x' str_step += LETTERS_ON_BOARD[destination_x] + str(destination_y+1) self.result_notation_text += str_step def add_step_to_notation_if_castling(self, source_x, source_y, destination_x, destination_y): print('Da, castling dolzhna bit') if (destination_x, destination_y) == (2, 0): self.result_notation_text += '\n' + self.get_number_of_string_in_notation() + '0-0-0 ' if (destination_x, destination_y) == (2, 7): self.result_notation_text += '0-0-0' if (destination_x, destination_y) == (6, 0): self.result_notation_text += '\n' + self.get_number_of_string_in_notation() + '0-0 ' if (destination_x, destination_y) == (6, 7): self.result_notation_text += '0-0 '
def build(self): self.from_move = None self.to_move = None self.chessboard = ChessBoard() self.analysis_board = ChessBoard() self.squares = [] self.use_engine = False self.last_touch_down_move = None self.last_touch_up_move = None parent = BoxLayout(size_hint=(1,1)) grid = GridLayout(cols = 8, rows = 8, spacing = 0, size_hint=(1, 1)) for i, name in enumerate(SQUARES): bt = Image(allow_stretch=True) bt.sq = i bt.name = name # bt.border = [0,0,0,0] if i in light_squares: bt.sq_color = "l" bt.background_down = "img/empty-l.png" # bt.background_color=[1,1,1,1] else: bt.sq_color = "d" bt.background_down = "img/empty-d.png" # bt.background_color=[0,0,0,0] # print i # bt.bind(on_press=self.callback) bt.bind(on_touch_down=self.touch_down_move) bt.bind(on_touch_up=self.touch_up_move) # bt.bind(on_touch_up=self.touch_move) grid.add_widget(bt) self.squares.append(bt) b = BoxLayout(size_hint=(0.15,0.15)) ## Spacers # b.add_widget(Button(spacing=1)) # b.add_widget(Button(spacing=1)) # b.add_widget(Button(spacing=1)) # Move control buttons # back_bt = Button(markup=True) # # back_bt.background_normal="img/empty-l.png" # back_bt.text="[color=ff3333]Back[/color]" # back_bt.bind(on_press=self.back) # b.add_widget(back_bt) # save_bt = Button(markup=True) #fwd_bt.background_normal="img/empty-d.png" save_bt.text="[color=3333ff]Save[/color]" # save_bt.text="Save" save_bt.bind(on_press=self.save) b.add_widget(save_bt) # b.add_widget(Button(spacing=10)) # b.add_widget(Button(spacing=10)) # b.add_widget(Button(spacing=10)) # grid.add_widget(b) # board_box.add_widget(grid) # board_box.add_widget(b) # fen_input = TextInput(text="FEN", focus=True, multiline=False) # def on_fen_input(instance): # self.chessboard.setFEN(instance.text) # self.refresh_board() ## print 'The widget', instance.text # # fen_input.bind(on_text_validate=on_fen_input) ## self._keyboard.bind(on_key_down=self._on_keyboard_down) # # # b.add_widget(fen_input) settings_bt = Button(markup=True, text='Setup') settings_bt.bind(on_press=self.go_to_settings) b.add_widget(settings_bt) # self.root.current='settings' parent.add_widget(grid) info_grid = GridLayout(cols = 1, rows = 4, spacing = 1, size_hint=(0.3, 1), orientation='vertical') info_grid.add_widget(b) self.game_score = ScrollableLabel('New Game', ref_callback=self.go_to_move) info_grid.add_widget(self.game_score) self.engine_score = ScrollableLabel('[ref=engine_toggle]Analysis[/ref]', ref_callback=self.add_eng_moves) info_grid.add_widget(self.engine_score) info_grid.add_widget(Button(text="Text")) parent.add_widget(info_grid) self.refresh_board() platform = kivy.utils.platform() self.uci_engine = None if self.is_desktop(): self._keyboard = Window.request_keyboard( self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down) self.start_engine_thread() sm = ScreenManager(transition=SlideTransition()) board_screen = Screen(name='main') board_screen.add_widget(parent) sm.add_widget(board_screen) settings_screen = SettingsScreen(name='settings') settings_screen.add_widget(self.generate_settings()) sm.add_widget(settings_screen) return sm
class Chess_app(App): def generate_settings(self): settings_panel = Settings() #create instance of Settings # def add_one_panel(from_instance): # panel = SettingsPanel(title="I like trains", settings=self) # panel.add_widget(AsyncImage(source="http://i3.kym-cdn.com/entries/icons/original/000/004/795/I-LIKE-TRAINS.jpg")) # settings_panel.add_widget(panel) # print "Hello World from ", from_instance panel = SettingsPanel(title="Engine") #create instance of left side panel item1 = SettingItem(panel=panel, title="Board") #create instance of one item in left side panel item2 = SettingItem(panel=panel, title="Level") #create instance of one item in left side panel # item2 = SettingTitle(title="Level") #another widget in left side panel # button = Button(text="Add one more panel") # item1.add_widget(button) #add widget to item1 in left side panel # button.bind(on_release=add_one_panel) #bind that button to function panel.add_widget(item1) # add item1 to left side panel panel.add_widget(item2) # add item2 to left side panel settings_panel.add_widget(panel) #add left side panel itself to the settings menu def go_back(): self.root.current = 'main' settings_panel.on_close=go_back return settings_panel # show the settings interface # # parent = BoxLayout(size_hint=(1, 1)) # bt = Button(text='Settings') # parent.add_widget(bt) # # def go_back(instance): # self.root.current = 'main' # # back_bt = Button(text='Back to Main') # back_bt.bind(on_press=go_back) # parent.add_widget(back_bt) # # return parent def build(self): self.from_move = None self.to_move = None self.chessboard = ChessBoard() self.analysis_board = ChessBoard() self.squares = [] self.use_engine = False self.last_touch_down_move = None self.last_touch_up_move = None parent = BoxLayout(size_hint=(1,1)) grid = GridLayout(cols = 8, rows = 8, spacing = 0, size_hint=(1, 1)) for i, name in enumerate(SQUARES): bt = Image(allow_stretch=True) bt.sq = i bt.name = name # bt.border = [0,0,0,0] if i in light_squares: bt.sq_color = "l" bt.background_down = "img/empty-l.png" # bt.background_color=[1,1,1,1] else: bt.sq_color = "d" bt.background_down = "img/empty-d.png" # bt.background_color=[0,0,0,0] # print i # bt.bind(on_press=self.callback) bt.bind(on_touch_down=self.touch_down_move) bt.bind(on_touch_up=self.touch_up_move) # bt.bind(on_touch_up=self.touch_move) grid.add_widget(bt) self.squares.append(bt) b = BoxLayout(size_hint=(0.15,0.15)) ## Spacers # b.add_widget(Button(spacing=1)) # b.add_widget(Button(spacing=1)) # b.add_widget(Button(spacing=1)) # Move control buttons # back_bt = Button(markup=True) # # back_bt.background_normal="img/empty-l.png" # back_bt.text="[color=ff3333]Back[/color]" # back_bt.bind(on_press=self.back) # b.add_widget(back_bt) # save_bt = Button(markup=True) #fwd_bt.background_normal="img/empty-d.png" save_bt.text="[color=3333ff]Save[/color]" # save_bt.text="Save" save_bt.bind(on_press=self.save) b.add_widget(save_bt) # b.add_widget(Button(spacing=10)) # b.add_widget(Button(spacing=10)) # b.add_widget(Button(spacing=10)) # grid.add_widget(b) # board_box.add_widget(grid) # board_box.add_widget(b) # fen_input = TextInput(text="FEN", focus=True, multiline=False) # def on_fen_input(instance): # self.chessboard.setFEN(instance.text) # self.refresh_board() ## print 'The widget', instance.text # # fen_input.bind(on_text_validate=on_fen_input) ## self._keyboard.bind(on_key_down=self._on_keyboard_down) # # # b.add_widget(fen_input) settings_bt = Button(markup=True, text='Setup') settings_bt.bind(on_press=self.go_to_settings) b.add_widget(settings_bt) # self.root.current='settings' parent.add_widget(grid) info_grid = GridLayout(cols = 1, rows = 4, spacing = 1, size_hint=(0.3, 1), orientation='vertical') info_grid.add_widget(b) self.game_score = ScrollableLabel('New Game', ref_callback=self.go_to_move) info_grid.add_widget(self.game_score) self.engine_score = ScrollableLabel('[ref=engine_toggle]Analysis[/ref]', ref_callback=self.add_eng_moves) info_grid.add_widget(self.engine_score) info_grid.add_widget(Button(text="Text")) parent.add_widget(info_grid) self.refresh_board() platform = kivy.utils.platform() self.uci_engine = None if self.is_desktop(): self._keyboard = Window.request_keyboard( self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down) self.start_engine_thread() sm = ScreenManager(transition=SlideTransition()) board_screen = Screen(name='main') board_screen.add_widget(parent) sm.add_widget(board_screen) settings_screen = SettingsScreen(name='settings') settings_screen.add_widget(self.generate_settings()) sm.add_widget(settings_screen) return sm def go_to_settings(self, instance): self.root.current='settings' def go_to_move(self, instance, value): # print 'Going back to move.. ', value move_num, color = value.split(":") half_move_num = int(move_num)*2 - 1 # print "half_move_num:%d"%half_move_num if color == 'b': half_move_num+=1 self.chessboard.gotoMove(half_move_num) self.refresh_board() def add_eng_moves(self, instance, value): if value=="engine_toggle": # print "Bringing up engine menu" if self.use_engine: self.use_engine = False self.uci_engine.stop() else: self.use_engine = True self.refresh_board() else: for i, mv in enumerate(self.engine_score.raw): if i>=1: break self.chessboard.addTextMove(mv) self.refresh_board() def is_desktop(self): platform = kivy.utils.platform() # print platform return True if platform.startswith('win') or platform.startswith('linux') or platform.startswith('mac') else False def back(self, obj): self.chessboard.undo() self.refresh_board() def _keyboard_closed(self): # print 'My keyboard have been closed!' self._keyboard.unbind(on_key_down=self.back) self._keyboard = None def start_engine_thread(self): t = Thread(target=self.update_engine_output, args=(self.engine_score,)) t.daemon = True # thread dies with the program t.start() def start_engine(self): # self.use_engine = False uci_engine = UCIEngine() uci_engine.start() uci_engine.configure({'Threads': '1'}) #uci_engine.configure({'Use Sleeping Threads': 'false'}) # Wait until the uci connection is setup while not uci_engine.ready: uci_engine.registerIncomingData() uci_engine.startGame() # uci_engine.requestMove() self.uci_engine=uci_engine def update_engine_output(self, output): if not self.use_engine: self.start_engine() def parse_score(line): self.analysis_board.setFEN(self.chessboard.getFEN()) tokens = line.split() try: score_index = tokens.index('score') except ValueError: score_index = -1 score = None move_list = [] if score_index!=-1 and tokens[score_index+1]=="cp": score = float(tokens[score_index+2])/100*1.0 try: line_index = tokens.index('pv') for mv in tokens[line_index+1:]: self.analysis_board.addTextMove(mv) move_list.append(self.analysis_board.getLastTextMove()) except ValueError: line_index = -1 variation = self.generate_move_list(move_list,start_move_num=self.chessboard.getCurrentMove()+1) if line_index!=-1 else None #del analysis_board if variation and score: return move_list, "[b]%s[/b][color=0d4cd6][ref=engine_toggle] Stop[/ref][/color]\n[color=77b5fe]%s[/color]" %(score,"".join(variation)) while True: if self.use_engine: line = self.uci_engine.getOutput() if line: #out_score = None out_score = parse_score(line) if out_score: raw_line, cleaned_line = out_score if cleaned_line: output.children[0].text = cleaned_line if raw_line: output.raw = raw_line elif output.children[0].text != ANALYSIS_HEADER: output.children[0].text = ANALYSIS_HEADER def _on_keyboard_down(self, keyboard, keycode, text, modifiers): # print 'The key', keycode, 'have been pressed' # print ' - text is %r' % text # print ' - modifiers are %r' % modifiers # Keycode is composed of an integer + a string # If we hit escape, release the keyboard if keycode[1] == 'escape': keyboard.release() if keycode[1] == 'left': self.back(None) elif keycode[1] == 'right': self.fwd(None) # Return True to accept the key. Otherwise, it will be used by # the system. return True def fwd(self, obj): self.chessboard.redo() self.refresh_board() def save(self, obj): f = open('game.pgn','w') f.write('Game Header - Analysis \n\n') f.write(self.generate_move_list(self.chessboard.getAllTextMoves(),raw=True)) f.close() def touch_down_move(self, img, touch): if not img.collide_point(touch.x, touch.y): return # print "touch_move" # print touch mv = img.name squares = [item for sublist in self.chessboard.getBoard() for item in sublist] if squares[SQUARES.index(mv)]!='.': # self.from_move = move self.last_touch_down_move = mv # self.process_move(mv) def touch_up_move(self, img, touch): if not img.collide_point(touch.x, touch.y): return # print "touch_move" # print touch mv = img.name self.last_touch_up_move = img.name if self.last_touch_up_move != self.last_touch_down_move: self.process_move() def process_move(self): if self.chessboard.addTextMove(self.last_touch_down_move+self.last_touch_up_move): self.refresh_board() def generate_move_list(self, all_moves, start_move_num = 1, raw = False): score = "" # if raw: # return " ".join(all_moves) for i, mv in it.izip(it.count(start_move_num), all_moves): move = "b" if i % 2 == 1: score += "%d. " % ((i + 1) / 2) move = "w" if mv: if raw: score += " % s" % mv if i % 5 == 0: score += "\n" else: score += " [ref=%d:%s] %s [/ref]"%((i + 1) / 2, move, mv) return score def refresh_board(self): # flatten lists into one list of 64 squares squares = [item for sublist in self.chessboard.getBoard() for item in sublist] for i, p in enumerate(squares): sq = self.squares[i] if p==".": sq.source=sq.background_down if p!=".": p_color = 'w' if p.isupper() else 'b' sq.source="img/pieces/Merida/"+sq.sq_color+p_color+p.lower()+".png" # Update game notation all_moves = self.chessboard.getAllTextMoves() if all_moves: score = self.generate_move_list(all_moves) self.game_score.children[0].text="[color=fcf7da]%s[/color]"%score # self.game_score.raw = self.generate_move_list(all_moves, raw=True) if self.use_engine: #self.analysis_board.setFEN(self.chessboard.getFEN()) self.uci_engine.stop() self.uci_engine.reportMoves(self.chessboard.getAllTextMoves(format=0, till_current_move=True)) # self.uci_engine.reportMove(self.chessboard.getLastTextMove(format=0)) self.uci_engine.requestMove()
def gameTick(self): self.updateConsideringLine() if self.state == UserInterface.STATE_WAITING_FOR_START_POS: if np.array_equal(self.boardscan, self.startingPos): print "NEW GAME: Creating chess board" self.chess = ChessBoard() self.lastBoardscan = self.boardscan self.engine.newGame() self.topHeading = self.your_turn self.dirtyUi = True self.state = UserInterface.STATE_WAITING_FOR_BOARD_CHANGE elif self.state == UserInterface.STATE_WAITING_FOR_ENGINE: if self.engine.bestmove is not None: self.requestedMove = self.engine.bestmove self.considering = [] self.state = UserInterface.STATE_WAITING_FOR_BOARD_CHANGE self.topHeading = self.my_turn_move_piece self.dirtyUi = True self.renderBoard() elif self.state == UserInterface.STATE_WAITING_FOR_BOARD_CHANGE: changes = self.boardscan - self.lastBoardscan numChanges = np.count_nonzero(changes) if numChanges == 2 or numChanges == 3 or numChanges == 4: self.dirtyUi = True print "" print "changes:\n" + str(changes) moveFrom = () moveTo = () nonzeroChanges = changes.nonzero() print "nonzeroChanges: " + str(nonzeroChanges) print "len(nonzeroChanges[0]) = %d" % len(nonzeroChanges[0]) for i in range(len(nonzeroChanges[0])): change = (nonzeroChanges[1][i], nonzeroChanges[0][i]) value = changes[change[1], change[0]] colorBefore = self.lastBoardscan[change[1], change[0]] print "\tchange: %s\tvalue: %s\tcolorBefore: %s" % (str(change), value, colorBefore) if self.chess.getTurn() == ChessBoard.WHITE: # WHITE's turn if value == -1: if numChanges != 4 or (change == (4,7)): moveFrom = change else: if numChanges == 4: if change == (6,7) or change == (2,7): moveTo = change elif numChanges == 3: if colorBefore == 0: moveTo = change else: moveTo = change else: # BLACK's turn if value == 1: if numChanges != 4 or (change == (4,0)): print "setting moveFrom to ", change moveFrom = change else: if numChanges == 4: if change == (6,0) or change == (2,0): print "setting moveTo to ", change moveTo = change elif numChanges == 3: if colorBefore == 0: print "setting moveTo to ", change moveTo = change else: moveTo = change print "moveFrom: " + str(moveFrom) print "moveTo: " + str(moveTo) if moveFrom and moveTo: print "getTurn before:", self.chess.getTurn() result = self.chess.addMove(moveFrom, moveTo) print "getTurn after:", self.chess.getTurn() if result is False: print "Could not make move: ", self.chess.getReason() else: lastMove = string.replace(self.chess.getLastTextMove(ChessBoard.AN), '-', '') cheater = False if self.requestedMove is not None and self.requestedMove != lastMove: cheater = True if self.chess.isCheck(): print "**** CHECK ****" self.bottomHeading = self.check else: self.bottomHeading = None self.requestedMove = None self.lastBoardscan = self.boardscan self.chess.printBoard() print "Last move type: " + str(self.chess.getLastMoveType()) print "New FEN: " + self.chess.getFEN() # Check if game is over if self.chess.isGameOver(): result = self.chess.getGameResult() if result == ChessBoard.WHITE_WIN: print "**** WHITE WINS ****" elif result == ChessBoard.BLACK_WIN: print "**** BLACK WINS ****" self.bottomHeading = self.checkmate_suckah else: print "**** STALEMATE ****" self.state = UserInterface.STATE_GAME_OVER elif self.chess.getTurn() == ChessBoard.BLACK: # It's black's turn, engage the engine self.topHeading = self.one_moment_please self.engine.makeMove(self.chess.getFEN()) self.state = UserInterface.STATE_WAITING_FOR_ENGINE else: if cheater: self.topHeading = self.your_turn_cheater else: self.topHeading = self.your_turn self.renderBoard() elif numChanges != 0: print "Invalid number of board changes: ", numChanges self.cv.reset_board() # Set boardscan to the last one just so we don't keep analyzing it until next scan comes in self.boardscan = self.lastBoardscan self.renderBoard()
pieces[1]["P"] = pygame.image.load(chessboardDirectory + "/img/wpb.png") pieces[1]["."] = pygame.image.load(chessboardDirectory + "/img/b.png") except ImportError: prettyBoard = False def drawPrettyBoard(board): for y, rank in enumerate(board): for x, p in enumerate(rank): pygameScreen.blit(pieces[(x+y)%2][p],(x*60,y*60)) if os.path.isfile("pnl.png"): pnl = pygame.image.load("pnl.png") pygameScreen.blit(pnl, (0,480)) pygame.display.flip() chess = ChessBoard() b = book.Book() prevSeq = None drops = 0 f = feed.Feed() ##p = pnl.Pnl(sys.argv[1]) stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.curs_set(0) stdscr.keypad(1)