def tip_mobility(model, ply, phase): board = model.getBoardAtPly(ply).board colorBackup = board.color # People need a chance to get developed # if model.ply < 16: # return board.setColor(WHITE) wmoves = len([ move for move in genAllMoves(board) if KNIGHT <= board.arBoard[FCORD(move)] <= QUEEN and bitPosArray[TCORD(move)] & brank48[WHITE] and staticExchangeEvaluate(board, move) >= 0 ]) board.setColor(BLACK) bmoves = len([ move for move in genAllMoves(board) if KNIGHT <= board.arBoard[FCORD(move)] <= QUEEN and bitPosArray[TCORD(move)] & brank48[BLACK] and staticExchangeEvaluate(board, move) >= 0 ]) board.setColor(colorBackup) if wmoves - phase >= (bmoves + 1) * 7: yield wmoves - bmoves, _("Black has a rather cramped position") elif wmoves - phase >= (bmoves + 1) * 3: yield wmoves - bmoves, _("Black has a slightly cramped position") elif bmoves - phase >= (wmoves + 1) * 7: yield wmoves - bmoves, _("White has a rather cramped position") elif bmoves - phase >= (wmoves + 1) * 3: yield wmoves - bmoves, _("White has a slightly cramped position")
def tip_mobility(model, ply, phase): board = model.getBoardAtPly(ply).board colorBackup = board.color # People need a chance to get developed # if model.ply < 16: # return board.setColor(WHITE) wmoves = len([move for move in genAllMoves(board) if KNIGHT <= board.arBoard[FCORD(move)] <= QUEEN and bitPosArray[TCORD(move)] & brank48[WHITE] and staticExchangeEvaluate(board, move) >= 0]) board.setColor(BLACK) bmoves = len([move for move in genAllMoves(board) if KNIGHT <= board.arBoard[FCORD(move)] <= QUEEN and bitPosArray[TCORD(move)] & brank48[BLACK] and staticExchangeEvaluate(board, move) >= 0]) board.setColor(colorBackup) if wmoves - phase >= (bmoves + 1) * 7: yield wmoves - bmoves, _("Black has a rather cramped position") elif wmoves - phase >= (bmoves + 1) * 3: yield wmoves - bmoves, _("Black has a slightly cramped position") elif bmoves - phase >= (wmoves + 1) * 7: yield wmoves - bmoves, _("White has a rather cramped position") elif bmoves - phase >= (wmoves + 1) * 3: yield wmoves - bmoves, _("White has a slightly cramped position")
def test_apply_pop(self): """Testing Atomic applyMove popMove""" board = LBoard(variant=ATOMICCHESS) board.applyFen(FEN) print(board) hist_exploding_around0 = [a[:] for a in board.hist_exploding_around] print_apply_pop = False for lmove1 in genAllMoves(board): board.applyMove(lmove1) if board.opIsChecked(): if print_apply_pop: print("popMove1 (invalid)", Move(lmove1)) board.popMove() continue hist_exploding_around1 = [ a[:] for a in board.hist_exploding_around ] for lmove2 in genAllMoves(board): board.applyMove(lmove2) if print_apply_pop: print(" applyMove2", Move(lmove2)) if board.opIsChecked(): if print_apply_pop: print(" popMove2 (invalid)", Move(lmove2)) board.popMove() continue hist_exploding_around2 = [ a[:] for a in board.hist_exploding_around ] for lmove3 in genAllMoves(board): board.applyMove(lmove3) if print_apply_pop: print(" applyMove3", Move(lmove3)) if board.opIsChecked(): if print_apply_pop: print(" popMove3 (invalid)", Move(lmove3)) board.popMove() continue board.popMove() if print_apply_pop: print(" popMove3", Move(lmove3)) self.assertEqual(hist_exploding_around2, board.hist_exploding_around) board.popMove() if print_apply_pop: print(" popMove2", Move(lmove2)) self.assertEqual(hist_exploding_around1, board.hist_exploding_around) board.popMove() if print_apply_pop: print("popMove1", Move(lmove1)) self.assertEqual(hist_exploding_around0, board.hist_exploding_around)
def test_apply_pop(self): """Testing Atomic applyMove popMove""" board = LBoard(variant=ATOMICCHESS) board.applyFen(FEN1) print(board) hist_exploding_around0 = [a[:] for a in board.hist_exploding_around] print_apply_pop = False for lmove1 in genAllMoves(board): board.applyMove(lmove1) if board.opIsChecked(): if print_apply_pop: print("popMove1 (invalid)", Move(lmove1)) board.popMove() continue hist_exploding_around1 = [a[:] for a in board.hist_exploding_around] for lmove2 in genAllMoves(board): board.applyMove(lmove2) if print_apply_pop: print(" applyMove2", Move(lmove2)) if board.opIsChecked(): if print_apply_pop: print(" popMove2 (invalid)", Move(lmove2)) board.popMove() continue hist_exploding_around2 = [a[:] for a in board.hist_exploding_around] for lmove3 in genAllMoves(board): board.applyMove(lmove3) if print_apply_pop: print(" applyMove3", Move(lmove3)) if board.opIsChecked(): if print_apply_pop: print(" popMove3 (invalid)", Move(lmove3)) board.popMove() continue board.popMove() if print_apply_pop: print(" popMove3", Move(lmove3)) self.assertEqual(hist_exploding_around2, board.hist_exploding_around) board.popMove() if print_apply_pop: print(" popMove2", Move(lmove2)) self.assertEqual(hist_exploding_around1, board.hist_exploding_around) board.popMove() if print_apply_pop: print("popMove1", Move(lmove1)) self.assertEqual(hist_exploding_around0, board.hist_exploding_around)
def test_gating_castle_at_rook_wOO(self): FEN = "r2qk2r/pppbbppp/4pn2/1N1p4/1n1P4/4PN2/PPPBBPPP/R2QK2R[heHE] w KQkq - 10 8" board = LBoard(SCHESS) board.applyFen(FEN) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) print("--------") print(board) self.assertIn("h1e1h", moves) self.assertIn("h1e1e", moves) self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O/Hh1'))), 'h1e1h') self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O/Eh1'))), 'h1e1e') self.assertEqual(toSAN(board, newMove(H1, E1, HAWK_GATE_AT_ROOK)), "O-O/Hh1") self.assertEqual(toSAN(board, newMove(H1, E1, ELEPHANT_GATE_AT_ROOK)), "O-O/Eh1") fen = board.asFen() move = parseAN(board, "h1e1e") board.applyMove(move) print("h1e1e") print(board) self.assertEqual(placement(board.asFen()), "r2qk2r/pppbbppp/4pn2/1N1p4/1n1P4/4PN2/PPPBBPPP/R2Q1RKE[heH]") board.popMove() self.assertEqual(placement(board.asFen()), placement(fen))
def test_gating_castle_at_rook_bOO(self): board = LBoard(SCHESS) board.applyFen(SCHESSSTART) for move in "e2e3 e7e6 g1f3 c7c6 c2c3 d7d5 d2d4 g8f6 h2h3 f6e4 d1c2 b8d7 f1d3 f7f5 e1g1e d8c7 e1e2 f8e7 c2d1".split(): board.applyMove(parseAN(board, move)) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) print("--------") print(board) self.assertIn("h8e8h", moves) self.assertIn("h8e8e", moves) fen = board.asFen() move = parseAN(board, "h8e8h") board.applyMove(move) print("h8e8e") print(board) self.assertEqual(placement(board.asFen()), "r1b2rkh/ppqnb1pp/2p1p3/3p1p2/3Pn3/2PBPN1P/PP2EPP1/RNBQ1RK1[eH]") board.popMove() self.assertEqual(placement(board.asFen()), placement(fen))
def test_gating_castle_at_rook_wOOO(self): board = LBoard(SCHESS) board.applyFen(SCHESSSTART) for move in "e2e4 d7d6 d1e2 c8d7 g1f3 g8f6 e4e5 f6d5 e2e4 d5b6 d2d3 d7c6 e4f5 c6d7 f5g5 g7g6 f3d4 h7h5 g5f4 d6e5 f4h4 f8g7 d4f3 d7g4 b1c3 f7f6 c3e4 d8d5 e4c3 d5c5 c1e3 c5d6 h2h3 g4f3 g2f3 e8g8h".split(): board.applyMove(parseAN(board, move)) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) print("--------") print(board) self.assertIn("a1e1h", moves) self.assertIn("a1e1e", moves) fen = board.asFen() parseAN(board, "a1e1e") board.applyMove(move) print("a1e1e") print(board) self.assertEqual(placement(board.asFen()), "rn2hrk1/ppp1p1b1/1n1q1pp1/4p2p/7Q/2NPBP1P/PPP2P2/E1KR1B1R[eH]") board.popMove() self.assertEqual(placement(board.asFen()), placement(fen))
def test_gating_king_move(self): board = LBoard(SCHESS) board.applyFen(SCHESSSTART) for move in "e2e3 e7e5 d1h5 d8e7 h5g4 b8c6 g1f3 d7d5 g4h4 e7c5 h4a4 e5e4 d2d4 c5e7 f3d2 e7b4 a4b4 c6b4".split(): board.applyMove(parseAN(board, move)) print("--------") print(board) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) self.assertIn("e1d1e", moves) self.assertIn("e1d1h", moves) fen = board.asFen() move = parseAN(board, "e1d1e") board.applyMove(move) print("e1d1e") print(board) self.assertEqual(placement(board.asFen()), "r1b1kbnr/ppp2ppp/8/3p4/1n1Pp3/4P3/PPPN1PPP/RNBKEB1R[heH]") board.popMove() self.assertEqual(placement(board.asFen()), placement(fen))
def test_pdb_database_get_bitboards(self): """Testing .pdb database get_bitboards""" db = self.load_test_pgn() board = LBoard() board.applyFen(FEN_START) for ply in range(4): bb_candidates = {} for lmove in genAllMoves(board): board.applyMove(lmove) if board.opIsChecked(): board.popMove() continue bb_candidates[board.friends[0] | board.friends[1]] = lmove board.popMove() bitboards = db.get_bitboards(ply, bb_candidates) print("==========") for row in bitboards: print(row) print("----------") self.assertEqual(len(bitboards), BITBOARD_COUNT[ply]) self.assertEqual(sum([row[1] for row in bitboards]), GAME_COUNT)
def check_or_mate(): board_clone = board.clone() board_clone.applyMove(move) sign = "" if board_clone.isChecked(): for altmove in genAllMoves(board_clone): if board.variant == ATOMICCHESS: from pychess.Variants.atomic import kingExplode if kingExplode( board_clone, altmove, 1 - board_clone.color ) and not kingExplode(board_clone, altmove, board_clone.color): sign = "+" break elif kingExplode(board_clone, altmove, board_clone.color): continue board_clone.applyMove(altmove) if board_clone.opIsChecked(): board_clone.popMove() continue sign = "+" break else: sign = "#" return sign
def simple_activity (model, ply, phase): board = model.getBoardAtPly(ply).board oldboard = model.getBoardAtPly(ply-1).board color = 1-board.color move = model.getMoveAtPly(ply-1).move fcord = FCORD(move) tcord = TCORD(move) board.setColor(1-board.color) moves = len([m for m in genAllMoves(board) if FCORD(m) == tcord]) board.setColor(1-board.color) oldmoves = len([m for m in genAllMoves(oldboard) if FCORD(m) == fcord]) if moves > oldmoves: yield (moves-oldmoves)/2, _("places a %(piece)s more active: %(cord)s") % { 'piece': reprPiece[board.arBoard[tcord]].lower(), 'cord': reprCord[tcord]}
def _genPossibleBoards(self, ply): possibleBoards = [] curboard = self.view.model.getBoardAtPly(ply, self.view.shownVariationIdx) for lmove in lmovegen.genAllMoves(curboard.board): move = Move(lmove) board = curboard.move(move) possibleBoards.append(board) return possibleBoards
def _genPossibleBoards(self, ply): possibleBoards = [] curboard = self.view.model.getBoardAtPly(ply) for lmove in lmovegen.genAllMoves(curboard.board): move = Move(lmove) board = curboard.move(move) possibleBoards.append(board) return possibleBoards
def simple_activity(model, ply, phase): board = model.getBoardAtPly(ply).board oldboard = model.getBoardAtPly(ply - 1).board move = model.getMoveAtPly(ply - 1).move fcord = FCORD(move) tcord = TCORD(move) board.setColor(1 - board.color) moves = len([m for m in genAllMoves(board) if FCORD(m) == tcord]) board.setColor(1 - board.color) oldmoves = len([m for m in genAllMoves(oldboard) if FCORD(m) == fcord]) if moves > oldmoves: yield (moves - oldmoves) / 2, _("places a %(piece)s more active: %(cord)s") % { 'piece': reprPiece[board.arBoard[tcord]].lower(), 'cord': reprCord[tcord]}
def get_bb_candidates(board): bb_candidates = {} for lmove in genAllMoves(board): board.applyMove(lmove) if board.opIsChecked(): board.popMove() continue bb_candidates[board.friends[0] | board.friends[1]] = lmove board.popMove() return bb_candidates
def _genPossibleBoards(self, ply): possibleBoards = [] if len(self.view.model.players) == 2 and self.view.model.isEngine2EngineGame(): return possibleBoards curboard = self.view.model.getBoardAtPly(ply, self.view.shownVariationIdx) for lmove in lmovegen.genAllMoves(curboard.board.clone()): move = Move(lmove) board = curboard.move(move) possibleBoards.append(board) return possibleBoards
def test_genAllMoves(self): """Testing validate move in Sittuyin variant""" board = SittuyinBoard(setup=FEN4) print(board) moves = set() for move in genAllMoves(board.board): moves.add(toAN(board.board, move)) # pseudo legal moves m = set(("f6e7", "f6f7", "f6g7", "f6e6", "f6g6", "f6e5", "f6f5", "f6g5", "d5c6", "d5d6", "d5e6=F", "d5c4=F")) self.assertEqual(moves, m)
def get_all_moves(request: WSGIRequest) -> JsonResponse: board = _get_board(request) from_coord = int(request.GET.get("index")) potential_moves = _get_potential_board_moves(from_coord, board) all_legal_moves = [Move(move) for move in genAllMoves(board.board)] legal_destinations = _get_legal_destinations(potential_moves, all_legal_moves) return JsonResponse({"moves": legal_destinations})
def _genPossibleBoards(self, ply): possibleBoards = [] if self.setup_position: return possibleBoards if len(self.view.model.players) == 2 and self.view.model.isEngine2EngineGame(): return possibleBoards curboard = self.view.model.getBoardAtPly(ply, self.view.shownVariationIdx) for lmove in lmovegen.genAllMoves(curboard.board.clone()): move = Move(lmove) board = curboard.move(move) possibleBoards.append(board) return possibleBoards
def test_promotion(self): # promotion moves FEN = "r4knr/1bpp1Pp1/pp3b2/q2pep1p/3N4/P1N5/1PPQBPPP/R1B1K2R[hHE] w KQ - 1 17" board = LBoard(SCHESS) board.applyFen(FEN) print("--------") print(board) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) self.assertIn("f7g8=H", moves) self.assertIn("f7g8=E", moves)
def test_parseFAN(self): """Testing parseFAN""" board = LBoard() board.applyFen("rnbqkbnr/8/8/8/8/8/8/RNBQKBNR w KQkq - 0 1") for lmove in genAllMoves(board): board.applyMove(lmove) if board.opIsChecked(): board.popMove() continue board.popMove() fan = toFAN(board, lmove) self.assertEqual(parseFAN(board, fan), lmove)
def test_white_promotion(self): FEN = "k7/7P/8/8/8/8/8/7K w - - 0 1" board = LBoard(LIGHTBRIGADECHESS) board.applyFen(FEN) print("--------") print(board) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) self.assertIn("h7h8=Q", moves) self.assertNotIn("h7h8", moves) self.assertNotIn("h7h8=R", moves) self.assertNotIn("h7h8=B", moves) self.assertNotIn("h7h8=N", moves) self.assertNotIn("h7h8=K", moves)
def test_black_promotion(self): FEN = "k7/8/8/8/8/8/p7/7K b - - 0 1" board = LBoard(LIGHTBRIGADECHESS) board.applyFen(FEN) print("--------") print(board) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) self.assertIn("a2a1=N", moves) self.assertNotIn("a2a1", moves) self.assertNotIn("a2a1=R", moves) self.assertNotIn("a2a1=B", moves) self.assertNotIn("a2a1=Q", moves) self.assertNotIn("a2a1=K", moves)
def perft(self, board, depth, prevmoves): if depth == 0: self.count += 1 return for move in genAllMoves(board): board.applyMove(move) if board.opIsChecked(): board.popMove() continue # Validator test board.popMove() self.assertTrue(validateMove(board, move)) board.applyMove (move) self.perft(board, depth-1, prevmoves) board.popMove()
def do_perft(board, depth, root): nodes = 0 if depth == 0: return 1 for move in genAllMoves(board): board.applyMove(move) if board.opIsChecked(): board.popMove() continue count = do_perft(board, depth-1, root-1) nodes += count board.popMove() if root > 0: print("%8s %10d %10d" % (toLAN(board, move), count, nodes)) return nodes
def perft(self, board, depth, prevmoves): if depth == 0: self.count += 1 return for move in genAllMoves(board): board.applyMove(move) if board.opIsChecked(): board.popMove() continue # Validator test board.popMove() self.assertTrue(validateMove(board, move)) board.applyMove(move) self.perft(board, depth - 1, prevmoves) board.popMove()
def update_tree(self, load_games=True): bb = self.board.friends[0] | self.board.friends[1] self.gamelist.ply = self.board.plyCount self.gamelist.chessfile.build_where_bitboards(self.board.plyCount, bb) self.gamelist.offset = 0 self.gamelist.chessfile.build_query() if load_games and self.filtered: self.gamelist.load_games() bb_candidates = {} for lmove in genAllMoves(self.board): self.board.applyMove(lmove) if self.board.opIsChecked(): self.board.popMove() continue bb_candidates[self.board.friends[0] | self.board.friends[1]] = lmove self.board.popMove() result = [] # print("get_bitboards() for %s bb_candidates" % len(bb_candidates)) bb_list = self.gamelist.chessfile.get_bitboards( self.board.plyCount + 1, bb_candidates) for bb, count, white_won, blackwon, draw, white_elo_avg, black_elo_avg in bb_list: try: result.append((bb_candidates[bb], count, white_won, blackwon, draw, white_elo_avg, black_elo_avg)) # print("OK ", bb, count, white_won, blackwon, draw, white_elo_avg, black_elo_avg) except KeyError: # print("KeyError", bb, count, white_won, blackwon, draw, white_elo_avg, black_elo_avg) pass self.clear_tree() for lmove, count, white_won, blackwon, draw, white_elo_avg, black_elo_avg in result: perf = 0 if not count else round( (white_won * 100. + draw * 50.) / count) elo_avg = white_elo_avg if self.board.color == WHITE else black_elo_avg self.liststore.append( [lmove, toSAN(self.board, lmove), count, perf, elo_avg])
def test_moves_from_startpos(self): board = LBoard(SCHESS) board.applyFen(SCHESSSTART) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) board.applyMove(move) board.popMove() self.assertEqual(placement(board.asFen()), placement(SCHESSSTART)) self.assertIn("b1a3e", moves) self.assertIn("b1a3h", moves) self.assertIn("b1c3e", moves) self.assertIn("b1c3h", moves) self.assertIn("g1f3e", moves) self.assertIn("g1f3h", moves) self.assertIn("g1h3e", moves) self.assertIn("g1h3h", moves)
def test_disambig_gating_san(self): FEN = "rnbqkb1r/ppp1pppp/3p1n2/8/2PP4/2N5/PP2PPPP/RHBQKBNR[Eeh] b KQACDEFGHkqabcdefh - 1 3" board = LBoard(SCHESS) board.applyFen(FEN) moves = set() for move in genAllMoves(board): moves.add(toAN(board, move)) print("--------") print(board) self.assertIn("f6d7", moves) self.assertNotIn("f6d7/H", moves) self.assertNotIn("f6d7/E", moves) self.assertIn("b8d7", moves) self.assertIn("b8d7h", moves) self.assertIn("b8d7e", moves) self.assertEqual(repr(Move.Move(parseSAN(board, 'Nfd7'))), 'f6d7') self.assertEqual(repr(Move.Move(parseSAN(board, 'Nbd7'))), 'b8d7') self.assertEqual(repr(Move.Move(parseSAN(board, 'Nbd7/H'))), 'b8d7h') self.assertEqual(repr(Move.Move(parseSAN(board, 'Nbd7/E'))), 'b8d7e')
def check_or_mate(): board_clone = board.clone() board_clone.applyMove(move) sign = "" if board_clone.isChecked(): for altmove in genAllMoves (board_clone): if board.variant == ATOMICCHESS: from pychess.Variants.atomic import kingExplode if kingExplode(board_clone, altmove, 1-board_clone.color) and \ not kingExplode(board_clone, altmove, board_clone.color): sign = "+" break elif kingExplode(board_clone, altmove, board_clone.color): continue board_clone.applyMove(altmove) if board_clone.opIsChecked(): board_clone.popMove() continue sign = "+" break else: sign = "#" return sign
def run(self): while True: try: line = raw_input() except EOFError: line = "quit" lines = line.split() try: if not lines: continue log.debug(line, extra={"task": "xboard"}) ########## CECP commands ########## # See http://home.hccnet.nl/h.g.muller/engine-intf.html if lines[0] == "xboard": pass elif lines[0] == "protover": stringPairs = [ "=".join( [k, '"%s"' % v if isinstance(v, str) else str(v)]) for k, v in self.features.items() ] self.print("feature %s" % " ".join(stringPairs)) self.print("feature done=1") elif lines[0] in ("accepted", "rejected"): # We only really care about one case: if tuple(lines) == ("rejected", "debug"): self.debug = False elif lines[0] == "new": self.__stopSearching() self.board = LBoard(NORMALCHESS) self.board.applyFen(FEN_START) self.outOfBook = False self.forced = False self.playingAs = BLACK self.clock[:] = self.basetime, self.basetime self.searchtime = 0 self.sd = MAXPLY if self.analyzing: self.__analyze() elif lines[0] == "variant": if len(lines) > 1: if lines[1] == "fischerandom": self.board.variant = FISCHERRANDOMCHESS elif lines[1] == "crazyhouse": self.board.variant = CRAZYHOUSECHESS self.board.iniHouse() elif lines[1] == "wildcastle": self.board.variant = WILDCASTLESHUFFLECHESS elif lines[1] == "losers": self.board.variant = LOSERSCHESS elif lines[1] == "suicide": self.board.variant = SUICIDECHESS elif lines[1] == "atomic": self.board.variant = ATOMICCHESS self.board.iniAtomic() elif lines[1] == "3check": self.board.variant = THREECHECKCHESS elif lines[1] == "kingofthehill": self.board.variant = KINGOFTHEHILLCHESS self.print("setup (PNBRQKpnbrqk) 8x8+0_fairy %s" % FEN_START) elif lines[1] == "asean": self.board = LBoard(ASEANCHESS) self.board.applyFen(ASEANSTART) elif lines[1] == "makruk": self.board = LBoard(MAKRUKCHESS) self.board.applyFen(MAKRUKSTART) elif lines[1] == "cambodian": self.board = LBoard(CAMBODIANCHESS) self.board.applyFen(KAMBODIANSTART) self.print( "setup (PN.R.M....SKpn.r.m....sk) 8x8+0_makruk %s" % KAMBODIANSTART) self.print("piece K& KiN") self.print("piece M& FifD") elif lines[1] == "sittuyin": self.board = LBoard(SITTUYINCHESS) self.board.applyFen(SITTUYINSTART) self.print( "setup (PN.R.F....SKpn.r.f....sk) 8x8+6_bughouse %s" % SITTUYINSTART) self.print("piece N& Nj@3") self.print("piece S& FfWj@3") self.print("piece F& Fjb@3") self.print("piece R& R@1") self.print("piece K& Kj@3") self.print("piece P& fmWfcFj@3") elif lines[0] == "quit": self.forced = True self.__stopSearching() sys.exit(0) elif lines[0] == "random": leval.random = True elif lines[0] == "force": if not self.forced and not self.analyzing: self.forced = True self.__stopSearching() elif lines[0] == "go": self.playingAs = self.board.color self.forced = False self.__go() elif lines[0] == "playother": self.playingAs = 1 - self.board.color self.forced = False # TODO: start pondering, if possible elif lines[0] in ("black", "white"): newColor = lines[0] == "black" and BLACK or WHITE self.__stopSearching() self.playingAs = 1 - newColor if self.board.color != newColor: self.board.setColor(newColor) self.board.setEnpassant(None) if self.analyzing: self.__analyze() elif lines[0] == "level": self.movestogo = int(lines[1]) inc = int(lines[3]) minutes = lines[2].split(":") # Per protocol spec, strip off any non-numeric suffixes. for i in range(len(minutes)): minutes[i] = re.match(r'\d*', minutes[i]).group() self.basetime = int(minutes[0]) * 60 if len(minutes) > 1 and minutes[1]: self.basetime += int(minutes[1]) self.clock[:] = self.basetime, self.basetime self.increment = inc, inc elif lines[0] == "st": self.searchtime = float(lines[1]) elif lines[0] == "sd": self.sd = int(lines[1]) # Unimplemented: nps elif lines[0] == "time": self.clock[self.playingAs] = float(lines[1]) / 100. elif lines[0] == "otim": self.clock[1 - self.playingAs] = float(lines[1]) / 100. elif lines[0] == "usermove": self.__stopSearching() try: move = parseAny(self.board, lines[1]) except ParsingError as e: self.print("Error (unknown command): %s" % lines[1]) self.print(self.board) continue if not validateMove(self.board, move): self.print("Illegal move: %s" % lines[1]) self.print(self.board) continue self.board.applyMove(move) self.playingAs = self.board.color if not self.forced and not self.analyzing: self.__go() if self.analyzing: self.__analyze() elif lines[0] == "?": if not self.forced and not self.analyzing: self.__stopSearching() elif lines[0] == "ping": self.print("pong %s" % lines[1]) elif lines[0] == "draw": if self.__willingToDraw(): self.print("offer draw") elif lines[0] == "result": # We don't really care what the result is at the moment. pass elif lines[0] == "setboard": self.__stopSearching() try: self.board = LBoard(self.board.variant) fen = " ".join(lines[1:]) self.board.applyFen( fen.replace("[", "/").replace("]", "")) except SyntaxError as e: self.print("tellusererror Illegal position: %s" % str(e)) # "edit" is unimplemented. See docs. Exiting edit mode returns to analyze mode. elif lines[0] == "hint": pass # TODO: Respond "Hint: MOVE" if we have an expected reply elif lines[0] == "bk": entries = getOpenings(self.board) if entries: totalWeight = sum(entry[1] for entry in entries) for entry in entries: self.print("\t%s\t%02.2f%%" % (toSAN(self.board, entry[0]), entry[1] * 100.0 / totalWeight)) elif lines[0] == "undo": self.__stopSearching() self.board.popMove() if self.analyzing: self.__analyze() elif lines[0] == "remove": self.__stopSearching() self.board.popMove() self.board.popMove() if self.analyzing: self.__analyze() elif lines[0] in ("hard", "easy"): self.ponder = (lines[0] == "hard") elif lines[0] in ("post", "nopost"): self.post = (lines[0] == "post") elif lines[0] == "analyze": self.analyzing = True self.__analyze() elif lines[0] in ("name", "rating", "ics", "computer"): pass # We don't care. # Unimplemented: pause, resume elif lines[0] == "memory": # FIXME: this is supposed to control the *total* memory use. if lsearch.searching: self.print("Error (already searching):", line) else: limit = int(lines[1]) if limit < 1: self.print("Error (limit too low):", line) else: pass # TODO implement #lsearch.setHashSize(limit) elif lines[0] == "cores": pass # We aren't SMP-capable. elif lines[0] == "egtpath": if len(lines) >= 3 and lines[1] == "gaviota": conf.set("egtb_path", conf.get("egtb_path", lines[2])) from pychess.Utils.lutils.lsearch import enableEGTB enableEGTB() elif lines[0] == "option" and len(lines) > 1: name, eq, value = lines[1].partition("=") if value: value = int( value ) # CECP spec says option values are *always* numeric if name == "skipPruneChance": if 0 <= value <= 100: self.skipPruneChance = value / 100.0 else: self.print( "Error (argument must be an integer 0..100): %s" % line) ########## CECP analyze mode commands ########## # See http://www.gnu.org/software/xboard/engine-intf.html#11 elif lines[0] == "exit": if self.analyzing: self.__stopSearching() self.analyzing = False # Periodic updates (".") are not implemented. ########## Custom commands ########## elif lines[0] == "moves": self.print(self.board) self.print([ toSAN(self.board, move) for move in genAllMoves(self.board) ]) elif lines[0] == "captures": self.print(self.board) self.print([ toSAN(self.board, move) for move in genCaptures(self.board) ]) elif lines[0] == "evasions": self.print(self.board) self.print([ toSAN(self.board, move) for move in genCheckEvasions(self.board) ]) elif lines[0] == "benchmark": benchmark() elif lines[0] == "profile": if len(lines) > 1: import cProfile cProfile.runctx("benchmark()", locals(), globals(), lines[1]) else: self.print("Usage: profile outputfilename") elif lines[0] == "perft": root = "0" if len(lines) < 3 else lines[2] depth = "1" if len(lines) == 1 else lines[1] if root.isdigit() and depth.isdigit(): perft(self.board, int(depth), int(root)) else: self.print("Error (arguments must be integer") elif len(lines) == 1: # A GUI without usermove support might try to send a move. try: move = parseAny(self.board, line) except: self.print("Error (unknown command): %s" % line) continue if not validateMove(self.board, move): self.print("Illegal move: %s" % lines[0]) self.print(self.board) continue self.__stopSearching() self.board.applyMove(move) self.playingAs = self.board.color if not self.forced and not self.analyzing: self.__go() if self.analyzing: self.__analyze() else: self.print("Error (unknown command): %s" % line) except IndexError: self.print("Error (missing argument): %s" % line)
def test_apply_pop(self): """Testing Crazyhouse applyMove popMove""" board = LBoard(variant=CRAZYHOUSECHESS) board.applyFen(FEN2) holding0 = (board.holding[0].copy(), board.holding[1].copy()) promoted0 = board.promoted[:] capture_promoting0 = board.capture_promoting hist_capture_promoting0 = board.hist_capture_promoting[:] print_board_promoted = False print_apply_pop = False for lmove1 in genAllMoves(board): # if lmove1 != parseAN(board, "c7b8=Q"): # continue board.applyMove(lmove1) if print_apply_pop: print("applyMove1", Move(lmove1), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) if board.opIsChecked(): if print_apply_pop: print("popMove1 (invalid)", Move(lmove1)) board.popMove() continue holding1 = (board.holding[0].copy(), board.holding[1].copy()) promoted1 = board.promoted[:] capture_promoting1 = board.capture_promoting hist_capture_promoting1 = board.hist_capture_promoting[:] for lmove2 in genAllMoves(board): # if lmove2 != parseAN(board, "e8f7"): # continue board.applyMove(lmove2) if print_apply_pop: print(" applyMove2", Move(lmove2), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) if board.opIsChecked(): if print_apply_pop: print(" popMove2 (invalid)", Move(lmove2)) board.popMove() continue holding2 = (board.holding[0].copy(), board.holding[1].copy()) promoted2 = board.promoted[:] capture_promoting2 = board.capture_promoting hist_capture_promoting2 = board.hist_capture_promoting[:] for lmove3 in genAllMoves(board): # if lmove3 != parseAN(board, "b8c8"): # continue board.applyMove(lmove3) if print_apply_pop: print(" applyMove3", Move(lmove3), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) if board.opIsChecked(): if print_apply_pop: print(" popMove3 (invalid)", Move(lmove3)) board.popMove() continue board.popMove() if print_apply_pop: print(" popMove3", Move(lmove3), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) self.assertEqual(holding2, board.holding) self.assertEqual(promoted2, board.promoted) self.assertEqual(capture_promoting2, board.capture_promoting) self.assertEqual(hist_capture_promoting2, board.hist_capture_promoting) board.popMove() if print_apply_pop: print(" popMove2", Move(lmove2), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) self.assertEqual(holding1, board.holding) self.assertEqual(promoted1, board.promoted) self.assertEqual(capture_promoting1, board.capture_promoting) self.assertEqual(hist_capture_promoting1, board.hist_capture_promoting) board.popMove() if print_apply_pop: print("popMove1", Move(lmove1), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) self.assertEqual(holding0, board.holding) self.assertEqual(promoted0, board.promoted) self.assertEqual(capture_promoting0, board.capture_promoting) self.assertEqual(hist_capture_promoting0, board.hist_capture_promoting)
def validateMove(board, move): return move in genAllMoves(board)
def test_apply_pop(self): """Testing Crazyhouse applyMove popMove""" board = LBoard(variant=CRAZYHOUSECHESS) board.applyFen(FEN1) holding0 = (board.holding[0].copy(), board.holding[1].copy()) promoted0 = board.promoted[:] capture_promoting0 = board.capture_promoting hist_capture_promoting0 = board.hist_capture_promoting[:] print_board_promoted = False print_apply_pop = False for lmove1 in genAllMoves(board): #if lmove1 != parseAN(board, "c7b8=Q"): # continue board.applyMove(lmove1) if print_apply_pop: print("applyMove1", Move(lmove1), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) if board.opIsChecked(): if print_apply_pop: print("popMove1 (invalid)", Move(lmove1)) board.popMove() continue holding1 = (board.holding[0].copy(), board.holding[1].copy()) promoted1 = board.promoted[:] capture_promoting1 = board.capture_promoting hist_capture_promoting1 = board.hist_capture_promoting[:] for lmove2 in genAllMoves(board): #if lmove2 != parseAN(board, "e8f7"): # continue board.applyMove(lmove2) if print_apply_pop: print(" applyMove2", Move(lmove2), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) if board.opIsChecked(): if print_apply_pop: print(" popMove2 (invalid)", Move(lmove2)) board.popMove() continue holding2 = (board.holding[0].copy(), board.holding[1].copy()) promoted2 = board.promoted[:] capture_promoting2 = board.capture_promoting hist_capture_promoting2 = board.hist_capture_promoting[:] for lmove3 in genAllMoves(board): #if lmove3 != parseAN(board, "b8c8"): # continue board.applyMove(lmove3) if print_apply_pop: print(" applyMove3", Move(lmove3), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) if board.opIsChecked(): if print_apply_pop: print(" popMove3 (invalid)", Move(lmove3)) board.popMove() continue board.popMove() if print_apply_pop: print(" popMove3", Move(lmove3), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) self.assertEqual(holding2, board.holding) self.assertEqual(promoted2, board.promoted) self.assertEqual(capture_promoting2, board.capture_promoting) self.assertEqual(hist_capture_promoting2, board.hist_capture_promoting) board.popMove() if print_apply_pop: print(" popMove2", Move(lmove2), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) self.assertEqual(holding1, board.holding) self.assertEqual(promoted1, board.promoted) self.assertEqual(capture_promoting1, board.capture_promoting) self.assertEqual(hist_capture_promoting1, board.hist_capture_promoting) board.popMove() if print_apply_pop: print("popMove1", Move(lmove1), board.holding, board.capture_promoting) if print_board_promoted: print(board.promoted) self.assertEqual(holding0, board.holding) self.assertEqual(promoted0, board.promoted) self.assertEqual(capture_promoting0, board.capture_promoting) self.assertEqual(hist_capture_promoting0, board.hist_capture_promoting)
def toSAN(board, move, localRepr=False): """ Returns a Short/Abbreviated Algebraic Notation string of a move The board should be prior to the move """ def check_or_mate(): board_clone = board.clone() board_clone.applyMove(move) sign = "" if board_clone.isChecked(): for altmove in genAllMoves(board_clone): if board.variant == ATOMICCHESS: from pychess.Variants.atomic import kingExplode if kingExplode(board_clone, altmove, 1 - board_clone.color) and \ not kingExplode(board_clone, altmove, board_clone.color): sign = "+" break elif kingExplode(board_clone, altmove, board_clone.color): continue board_clone.applyMove(altmove) if board_clone.opIsChecked(): board_clone.popMove() continue sign = "+" break else: sign = "#" return sign flag = move >> 12 if flag == NULL_MOVE: return "--" fcord = (move >> 6) & 63 if flag == KING_CASTLE: return "O-O%s" % check_or_mate() elif flag == QUEEN_CASTLE: return "O-O-O%s" % check_or_mate() tcord = move & 63 fpiece = fcord if flag == DROP else board.arBoard[fcord] tpiece = board.arBoard[tcord] part0 = "" part1 = "" if fpiece != PAWN or flag == DROP: if board.variant in (CAMBODIANCHESS, MAKRUKCHESS): part0 += reprSignMakruk[fpiece] elif board.variant == SITTUYINCHESS: part0 += reprSignSittuyin[fpiece] elif localRepr: part0 += localReprSign[fpiece] else: part0 += reprSign[fpiece] part1 = reprCord[tcord] if flag == DROP: return "%s@%s%s" % (part0, part1, check_or_mate()) if fpiece not in (PAWN, KING): xs = [] ys = [] board_clone = board.clone() for altmove in genAllMoves(board_clone, drops=False): mfcord = FCORD(altmove) if board_clone.arBoard[mfcord] == fpiece and \ mfcord != fcord and \ TCORD(altmove) == tcord: board_clone.applyMove(altmove) if not board_clone.opIsChecked(): xs.append(FILE(mfcord)) ys.append(RANK(mfcord)) board_clone.popMove() x = FILE(fcord) y = RANK(fcord) if ys or xs: if y in ys and x not in xs: # If we share rank with another piece, but not file part0 += reprFile[x] elif x in xs and y not in ys: # If we share file with another piece, but not rank part0 += reprRank[y] elif x in xs and y in ys: # If we share both file and rank with other pieces part0 += reprFile[x] + reprRank[y] else: # If we doesn't share anything, it is standard to put file part0 += reprFile[x] if tpiece != EMPTY or flag == ENPASSANT: if not (board.variant == SITTUYINCHESS and fcord == tcord): part1 = "x" + part1 if fpiece == PAWN: part0 += reprFile[FILE(fcord)] notat = part0 + part1 if flag in PROMOTIONS: if board.variant in (CAMBODIANCHESS, MAKRUKCHESS): notat += "=" + reprSignMakruk[PROMOTE_PIECE(flag)] elif board.variant == SITTUYINCHESS: notat += "=" + reprSignSittuyin[PROMOTE_PIECE(flag)] elif localRepr: notat += "=" + localReprSign[PROMOTE_PIECE(flag)] else: notat += "=" + reprSign[PROMOTE_PIECE(flag)] return "%s%s" % (notat, check_or_mate())
def perft(self, board, depth, prevmoves): if depth == 0: self.count += 1 return if board.isChecked(): # If we are checked we can use the genCheckEvasions function as well # as genAllMoves. Here we try both functions to ensure they return # the same result. nmoves = [] for nmove in genAllMoves(board): board.applyMove(nmove) if board.opIsChecked(): board.popMove() continue nmoves.append(nmove) board.popMove() # Validator test self.assertTrue(validateMove(board, nmove)) cmoves = [] for move in genCheckEvasions(board): board.applyMove(move) cmoves.append(move) board.popMove() # Validator test self.assertTrue(validateMove(board, move)) # This is not any kind of alphaBeta sort. Only int sorting, to make # comparison possible nmoves.sort() cmoves.sort() if nmoves == cmoves: for move in cmoves: prevmoves.append(toSAN (board, move)) board.applyMove(move) self.perft(board, depth-1, prevmoves) board.popMove() else: print board print "nmoves" for move in nmoves: print toSAN (board, move) print "cmoves" for move in cmoves: print toSAN (board, move) self.assertEqual(nmoves, cmoves) else: for move in genAllMoves(board): board.applyMove(move) if board.opIsChecked(): board.popMove() continue # Validator test board.popMove() self.assertTrue(validateMove(board, move)) # San test san = toSAN (board, move) try: move2 = parseSAN(board, san) except ParsingError, e: print prevmoves raise ParsingError, e self.assertEqual (move, move2) board.applyMove (move) self.perft(board, depth-1, prevmoves) board.popMove()
def run(self): while True: try: line = get_input() except EOFError: line = "quit" lines = line.split() try: if not lines: continue log.debug(line, extra={"task": "xboard"}) # CECP commands # See http://home.hccnet.nl/h.g.muller/engine-intf.html if lines[0] == "xboard": pass elif lines[0] == "protover": stringPairs = ["=".join([k, '"%s"' % v if isinstance( v, str) else str(v)]) for k, v in self.features.items()] self.print("feature %s" % " ".join(stringPairs)) self.print("feature done=1") elif lines[0] in ("accepted", "rejected"): # We only really care about one case: if tuple(lines) == ("rejected", "debug"): self.debug = False elif lines[0] == "new": self.__stopSearching() self.board = LBoard(NORMALCHESS) self.board.applyFen(FEN_START) self.outOfBook = False self.forced = False self.playingAs = BLACK self.clock[:] = self.basetime, self.basetime self.searchtime = 0 self.sd = MAXPLY if self.analyzing: self.__analyze() elif lines[0] == "variant": if len(lines) > 1: if lines[1] == "fischerandom": self.board.variant = FISCHERRANDOMCHESS elif lines[1] == "crazyhouse": self.board.variant = CRAZYHOUSECHESS self.board.iniHouse() elif lines[1] == "wildcastle": self.board.variant = WILDCASTLESHUFFLECHESS elif lines[1] == "losers": self.board.variant = LOSERSCHESS elif lines[1] == "suicide": self.board.variant = SUICIDECHESS elif lines[1] == "giveaway": self.board.variant = GIVEAWAYCHESS elif lines[1] == "atomic": self.board.variant = ATOMICCHESS self.board.iniAtomic() elif lines[1] == "3check": self.board.variant = THREECHECKCHESS elif lines[1] == "kingofthehill": self.board.variant = KINGOFTHEHILLCHESS self.print("setup (PNBRQKpnbrqk) 8x8+0_fairy %s" % FEN_START) elif lines[1] == "horde": self.board = LBoard(HORDECHESS) self.board.applyFen(HORDESTART) elif lines[1] == "asean": self.board = LBoard(ASEANCHESS) self.board.applyFen(ASEANSTART) elif lines[1] == "makruk": self.board = LBoard(MAKRUKCHESS) self.board.applyFen(MAKRUKSTART) elif lines[1] == "cambodian": self.board = LBoard(CAMBODIANCHESS) self.board.applyFen(KAMBODIANSTART) self.print( "setup (PN.R.M....SKpn.r.m....sk) 8x8+0_makruk %s" % KAMBODIANSTART) self.print("piece K& KiN") self.print("piece M& FifD") elif lines[1] == "sittuyin": self.board = LBoard(SITTUYINCHESS) self.board.applyFen(SITTUYINSTART) self.print( "setup (PN.R.F....SKpn.r.f....sk) 8x8+6_bughouse %s" % SITTUYINSTART) self.print("piece N& Nj@3") self.print("piece S& FfWj@3") self.print("piece F& Fjb@3") self.print("piece R& R@1") self.print("piece K& Kj@3") self.print("piece P& fmWfcFj@3") elif lines[0] == "quit": self.forced = True self.__stopSearching() sys.exit(0) elif lines[0] == "random": leval.random = True elif lines[0] == "force": if not self.forced and not self.analyzing: self.forced = True self.__stopSearching() elif lines[0] == "go": self.playingAs = self.board.color self.forced = False self.__go() elif lines[0] == "playother": self.playingAs = 1 - self.board.color self.forced = False # TODO: start pondering, if possible elif lines[0] in ("black", "white"): newColor = lines[0] == "black" and BLACK or WHITE self.__stopSearching() self.playingAs = 1 - newColor if self.board.color != newColor: self.board.setColor(newColor) self.board.setEnpassant(None) if self.analyzing: self.__analyze() elif lines[0] == "level": self.movestogo = int(lines[1]) inc = int(lines[3]) minutes = lines[2].split(":") # Per protocol spec, strip off any non-numeric suffixes. for i in range(len(minutes)): minutes[i] = re.match(r'\d*', minutes[i]).group() self.basetime = int(minutes[0]) * 60 if len(minutes) > 1 and minutes[1]: self.basetime += int(minutes[1]) self.clock[:] = self.basetime, self.basetime self.increment = inc, inc elif lines[0] == "st": self.searchtime = float(lines[1]) elif lines[0] == "sd": self.sd = int(lines[1]) # Unimplemented: nps elif lines[0] == "time": self.clock[self.playingAs] = float(lines[1]) / 100. elif lines[0] == "otim": self.clock[1 - self.playingAs] = float(lines[1]) / 100. elif lines[0] == "usermove": self.__stopSearching() try: move = parseAny(self.board, lines[1]) except ParsingError as err: self.print("Error (unknown command): %s" % lines[1]) self.print(self.board.prepr(ascii=ASCII)) continue if not validateMove(self.board, move): self.print("Illegal move: %s" % lines[1]) self.print(self.board.prepr(ascii=ASCII)) continue self.board.applyMove(move) self.playingAs = self.board.color if not self.forced and not self.analyzing: self.__go() if self.analyzing: self.__analyze() elif lines[0] == "?": if not self.forced and not self.analyzing: self.__stopSearching() elif lines[0] == "ping": self.print("pong %s" % lines[1]) elif lines[0] == "draw": if self.__willingToDraw(): self.print("offer draw") elif lines[0] == "result": # We don't really care what the result is at the moment. pass elif lines[0] == "setboard": self.__stopSearching() try: self.board = LBoard(self.board.variant) fen = " ".join(lines[1:]) self.board.applyFen(fen.replace("[", "/").replace("]", "")) except SyntaxError as err: self.print("tellusererror Illegal position: %s" % str(err)) # "edit" is unimplemented. See docs. Exiting edit mode returns to analyze mode. elif lines[0] == "hint": pass # TODO: Respond "Hint: MOVE" if we have an expected reply elif lines[0] == "bk": entries = getOpenings(self.board) if entries: totalWeight = sum(entry[1] for entry in entries) for entry in entries: self.print("\t%s\t%02.2f%%" % (toSAN(self.board, entry[0]), entry[1] * 100.0 / totalWeight)) elif lines[0] == "undo": self.__stopSearching() self.board.popMove() if self.analyzing: self.__analyze() elif lines[0] == "remove": self.__stopSearching() self.board.popMove() self.board.popMove() if self.analyzing: self.__analyze() elif lines[0] in ("hard", "easy"): self.ponder = (lines[0] == "hard") elif lines[0] in ("post", "nopost"): self.post = (lines[0] == "post") elif lines[0] == "analyze": self.analyzing = True self.__analyze() elif lines[0] in ("name", "rating", "ics", "computer"): pass # We don't care. # Unimplemented: pause, resume elif lines[0] == "memory": # FIXME: this is supposed to control the *total* memory use. if lsearch.searching: self.print("Error (already searching):", line) else: limit = int(lines[1]) if limit < 1: self.print("Error (limit too low):", line) else: pass # TODO implement # lsearch.setHashSize(limit) elif lines[0] == "cores": pass # We aren't SMP-capable. elif lines[0] == "egtpath": if len(lines) >= 3 and lines[1] == "gaviota": conf.set("egtb_path", conf.get("egtb_path", lines[2])) from pychess.Utils.lutils.lsearch import enableEGTB enableEGTB() elif lines[0] == "option" and len(lines) > 1: name, eq, value = lines[1].partition("=") if value: value = int( value ) # CECP spec says option values are *always* numeric if name == "skipPruneChance": if 0 <= value <= 100: self.skipPruneChance = value / 100.0 else: self.print( "Error (argument must be an integer 0..100): %s" % line) # CECP analyze mode commands # See http://www.gnu.org/software/xboard/engine-intf.html#11 elif lines[0] == "exit": if self.analyzing: self.__stopSearching() self.analyzing = False # Periodic updates (".") are not implemented. # Custom commands elif lines[0] == "moves": self.print(self.board.prepr(ascii=ASCII)) self.print([toSAN(self.board, move) for move in genAllMoves(self.board)]) elif lines[0] == "captures": self.print(self.board.prepr(ascii=ASCII)) self.print([toSAN(self.board, move) for move in genCaptures(self.board)]) elif lines[0] == "evasions": self.print(self.board.prepr(ascii=ASCII)) self.print([toSAN(self.board, move) for move in genCheckEvasions(self.board)]) elif lines[0] == "benchmark": if len(lines) > 1: benchmark(int(lines[1])) else: benchmark() elif lines[0] == "profile": if len(lines) > 1: import cProfile cProfile.runctx("benchmark()", locals(), globals(), lines[1]) else: self.print("Usage: profile outputfilename") elif lines[0] == "perft": root = "0" if len(lines) < 3 else lines[2] depth = "1" if len(lines) == 1 else lines[1] if root.isdigit() and depth.isdigit(): perft(self.board, int(depth), int(root)) else: self.print("Error (arguments must be integer") elif lines[0] == "stop_unittest": break elif len(lines) == 1: # A GUI without usermove support might try to send a move. try: move = parseAny(self.board, line) except ParsingError: self.print("Error (unknown command): %s" % line) continue if not validateMove(self.board, move): self.print("Illegal move: %s" % lines[0]) self.print(self.board.prepr(ascii=ASCII)) continue self.__stopSearching() self.board.applyMove(move) self.playingAs = self.board.color if not self.forced and not self.analyzing: self.__go() if self.analyzing: self.__analyze() else: self.print("Error (unknown command): %s" % line) except IndexError: self.print("Error (missing argument): %s" % line)
def perft(self, board, depth, prevmoves): if depth == 0: self.count += 1 return if board.isChecked(): # If we are checked we can use the genCheckEvasions function as well # as genAllMoves. Here we try both functions to ensure they return # the same result. nmoves = [] for nmove in genAllMoves(board): board.applyMove(nmove) if board.opIsChecked(): board.popMove() continue nmoves.append(nmove) board.popMove() # Validator test self.assertTrue(validateMove(board, nmove)) cmoves = [] for move in genCheckEvasions(board): board.applyMove(move) if board.opIsChecked(): board.popMove() continue cmoves.append(move) board.popMove() # Validator test self.assertTrue(validateMove(board, move)) # This is not any kind of alphaBeta sort. Only int sorting, to make # comparison possible nmoves.sort() cmoves.sort() if nmoves == cmoves: for move in cmoves: prevmoves.append(toSAN(board, move)) board.applyMove(move) self.perft(board, depth - 1, prevmoves) board.popMove() else: print(board) print("nmoves") for move in nmoves: print(toSAN(board, move)) print("cmoves") for move in cmoves: print(toSAN(board, move)) self.assertEqual(nmoves, cmoves) else: for move in genAllMoves(board): board.applyMove(move) if board.opIsChecked(): board.popMove() continue # Validator test board.popMove() self.assertTrue(validateMove(board, move)) # San test san = toSAN(board, move) # print(san) try: move2 = parseSAN(board, san) except ParsingError as e: print(prevmoves) raise ParsingError(e) self.assertEqual(move, move2) board.applyMove(move) self.perft(board, depth - 1, prevmoves) board.popMove()
def toSAN (board, move, localRepr=False): """ Returns a Short/Abbreviated Algebraic Notation string of a move The board should be prior to the move """ # Has to be importet at calltime, as lmovegen imports lmove #from lmovegen import genAllMoves def check_or_mate(): board_clone = board.clone() board_clone.applyMove(move) sign = "" if board_clone.isChecked(): for altmove in genAllMoves (board_clone): if board.variant == ATOMICCHESS: from pychess.Variants.atomic import kingExplode if kingExplode(board_clone, altmove, 1-board_clone.color) and \ not kingExplode(board_clone, altmove, board_clone.color): sign = "+" break elif kingExplode(board_clone, altmove, board_clone.color): continue board_clone.applyMove(altmove) if board_clone.opIsChecked(): board_clone.popMove() continue sign = "+" break else: sign = "#" return sign flag = move >> 12 if flag == NULL_MOVE: return "--" fcord = (move >> 6) & 63 if flag == KING_CASTLE: return "O-O%s" % check_or_mate() elif flag == QUEEN_CASTLE: return "O-O-O%s" % check_or_mate() tcord = move & 63 fpiece = fcord if flag == DROP else board.arBoard[fcord] tpiece = board.arBoard[tcord] part0 = "" part1 = "" if fpiece != PAWN or flag == DROP: if localRepr: part0 += localReprSign[fpiece] else: part0 += reprSign[fpiece] part1 = reprCord[tcord] if flag == DROP: return "%s@%s%s" % (part0, part1, check_or_mate()) if not fpiece in (PAWN, KING): xs = [] ys = [] board_clone = board.clone() for altmove in genAllMoves(board_clone, drops=False): mfcord = FCORD(altmove) if board_clone.arBoard[mfcord] == fpiece and \ mfcord != fcord and \ TCORD(altmove) == tcord: board_clone.applyMove(altmove) if not board_clone.opIsChecked(): xs.append(FILE(mfcord)) ys.append(RANK(mfcord)) board_clone.popMove() x = FILE(fcord) y = RANK(fcord) if ys or xs: if y in ys and not x in xs: # If we share rank with another piece, but not file part0 += reprFile[x] elif x in xs and not y in ys: # If we share file with another piece, but not rank part0 += reprRank[y] elif x in xs and y in ys: # If we share both file and rank with other pieces part0 += reprFile[x] + reprRank[y] else: # If we doesn't share anything, it is standard to put file part0 += reprFile[x] if tpiece != EMPTY or flag == ENPASSANT: part1 = "x" + part1 if fpiece == PAWN: part0 += reprFile[FILE(fcord)] notat = part0 + part1 if flag in PROMOTIONS: if localRepr: notat += "="+localReprSign[PROMOTE_PIECE(flag)] else: notat += "="+reprSign[PROMOTE_PIECE(flag)] return "%s%s" % (notat, check_or_mate())