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_san_move(self): board = LBoard(SCHESS) board.applyFen(SCHESSSTART) self.assertEqual(repr(Move.Move(parseSAN(board, 'Nf3/H'))), 'g1f3h') self.assertEqual(repr(Move.Move(parseSAN(board, 'Nf3/E'))), 'g1f3e') self.assertEqual(toSAN(board, newMove(G1, F3, HAWK_GATE)), "Nf3/H") self.assertEqual(toSAN(board, newMove(G1, F3, ELEPHANT_GATE)), "Nf3/E")
def test_gating_castle_at_rook_wOOO_SAN(self): FEN = "r2ek2r/5pp1/1pp1pnp1/2pp1h2/3P4/2P1PP2/PP1N2PP/R3K1HR/E w KQHEAkq - 2 16" board = LBoard(SCHESS) board.applyFen(FEN) self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O-O'))), 'e1c1') self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O-O/Ea1'))), 'a1e1e') self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O-O/Ee1'))), 'e1c1e') self.assertEqual(toSAN(board, newMove(E1, C1, QUEEN_CASTLE)), "O-O-O") self.assertEqual(toSAN(board, newMove(A1, E1, ELEPHANT_GATE_AT_ROOK)), "O-O-O/Ea1") self.assertEqual(toSAN(board, newMove(E1, C1, ELEPHANT_GATE)), "O-O-O/Ee1")
def test_default_gating_avail(self): board = LBoard(SCHESS) board.applyFen(SCHESSSTART) print(board) print(toString(board.virgin[0])) print(toString(board.virgin[1])) self.assertEqual(board.virgin[0], brank8[1]) self.assertEqual(board.virgin[1], brank8[0]) board = LBoard(SCHESS) FEN = "r1hqerk1/pp1nbppp/2pp1nb1/4p3/2PPP3/2N1B1PP/PP2NPB1/RH1QK2R/E w KQHEDA - 2 10" board.applyFen(FEN) print("-----------") print(board) move = parseSAN(board, "O-O") board.applyMove(move) castl = board.asFen().split()[2] self.assertNotIn("Q", castl) self.assertNotIn("K", castl) self.assertNotIn("E", castl) self.assertNotIn("H", castl)
def get_board(gamepgn, movenum): #make a pyboard at that spot. moves_to_here = gamepgn.moves[:movenum] board = LBoard.LBoard(variant=3) board.applyFen(gamepgn.fen) for move in moves_to_here : longmove = lmove.parseSAN(board, move) board.applyMove(longmove) return board
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 __onAmbiguousMove(self, errorManager, move): # This is really a fix for fics, but sometimes it is necessary if determineAlgebraicNotation(move) == SAN: self.board.popMove() move_ = parseSAN(self.board, move) lanmove = toLAN(self.board, move_) self.board.applyMove(move_) self.connection.bm.sendMove(lanmove) else: self.connection.cm.tellOpponent( "I'm sorry, I wanted to move %s, but FICS called " % move + "it 'Ambigious'. I can't find another way to express it, " + "so you can win") self.connection.bm.resign()
def __onAmbiguousMove (self, errorManager, move): # This is really a fix for fics, but sometimes it is necessary if determineAlgebraicNotation(move) == SAN: self.board.popMove() move_ = parseSAN(self.board, move) lanmove = toLAN(self.board, move_) self.board.applyMove(move_) self.connection.bm.sendMove(lanmove) else: self.connection.cm.tellOpponent( "I'm sorry, I wanted to move %s, but FICS called " % move + "it 'Ambigious'. I can't find another way to express it, " + "so you can win") self.connection.bm.resign()
def test_board(self): FEN = "r2qk2r/pppbbppp/4pn2/1N1p4/1n1P4/4PN2/PPPBBPPP/R2QK2R[heHE] w KQkq - 10 8" board = SchessBoard(setup=FEN) # print("--------") # print(board) self.assertEqual(board.data[0][7].color, WHITE) self.assertEqual(board.data[0][7].piece, ROOK) board = board.move(Move.Move(parseSAN(board.board, 'O-O/Hh1'))) # board.printPieces() self.assertEqual(board.data[0][7].color, WHITE) self.assertEqual(board.data[0][7].piece, HAWK) moves = "c3 c5 e3 d5 Nf3/E Nc6/H d4 e5 Nxe5 Nxe5 dxe5 Hxe5 e4 Nf6 Bf4/H Hc6 e5 Nd7 Be2 Nxe5 Bxe5 Hxe5 Bb5+ Bd7 Ee2 Bd6 Exe5+ Bxe5 Bxd7+ Qxd7/E" board = SchessBoard(setup=SCHESSSTART) for san in moves.split(): move = parseSAN(board.board, san) board = board.move(Move.Move(move)) # print(san) # board.printPieces() self.assertEqual(board.data[7][3].color, BLACK) self.assertEqual(board.data[7][3].piece, ELEPHANT)
def __onMoveCalculated (self, worker, sanmove): if worker.isCancelled() or not sanmove: return self.board.applyMove(parseSAN(self.board,sanmove)) self.connection.bm.sendMove(sanmove) self.extendlog(["Move sent %s" % sanmove])
def __onMoveCalculated(self, worker, sanmove): if worker.isCancelled() or not sanmove: return self.board.applyMove(parseSAN(self.board, sanmove)) self.connection.bm.sendMove(sanmove) self.extendlog(["Move sent %s" % sanmove])
def parse_string(self, string, board, position, variation=False): """Recursive parses a movelist part of one game. Arguments: srting - str (movelist) board - lboard (initial position) position - int (maximum ply to parse) variation- boolean (True if the string is a variation)""" boards = [] boards_append = boards.append last_board = board if variation: # this board used only to hold initial variation comments boards_append(LBoard(board.variant)) else: # initial game board boards_append(board) status = None parenthesis = 0 v_string = "" for m in re.finditer(pattern, string): group, text = m.lastindex, m.group(m.lastindex) if parenthesis > 0: v_string += ' '+text if group == VARIATION_END: parenthesis -= 1 if parenthesis == 0: v_last_board.children.append(self.parse_string(v_string[:-1], last_board.prev, position, variation=True)) v_string = "" continue elif group == VARIATION_START: parenthesis += 1 if parenthesis == 1: v_last_board = last_board if parenthesis == 0: if group == FULL_MOVE: if not variation: if position != -1 and last_board.plyCount >= position: break mstr = m.group(MOVE) try: lmove = parseSAN(last_board, mstr) except ParsingError, e: # TODO: save the rest as comment # last_board.children.append(string[m.start():]) notation, reason, boardfen = e.args ply = last_board.plyCount if ply % 2 == 0: moveno = "%d." % (ply/2+1) else: moveno = "%d..." % (ply/2+1) errstr1 = _("The game can't be read to end, because of an error parsing move %(moveno)s '%(notation)s'.") % { 'moveno': moveno, 'notation': notation} errstr2 = _("The move failed because %s.") % reason self.error = LoadingError (errstr1, errstr2) break except: ply = last_board.plyCount if ply % 2 == 0: moveno = "%d." % (ply/2+1) else: moveno = "%d..." % (ply/2+1) errstr1 = _( "Error parsing move %(moveno)s %(mstr)s") % {"moveno": moveno, "mstr": mstr} self.error = LoadingError (errstr1, "") break
def ondone(result): if not self.forced: self.board.applyMove(parseSAN(self.board, result)) self.print("move %s" % result)
def ondone (result): self.board.applyMove(parseSAN(self.board,result)) print "move %s" % result
def simple_parse_movetext(self, string, board, movelist, bitboards): """Parses a movelist part of one game. If find anything not being a move immediately returns False It fills list of lmoves parsed with parseSAN() and list of integers representing a board with occupied fields bitboard Arguments: srting - str (movelist) board - lboard (FEN_START) movelist - an empty array("H") to fill bitboards - an empty list to fill Return: True if parser find moves only.""" movelist_append = movelist.append for m in re.finditer(pattern, string): group, text = m.lastindex, m.group(m.lastindex) if group in (COMMENT_BRACE, COMMENT_NAG, VARIATION_END, VARIATION_START, COMMENT_REST): return False elif group == FULL_MOVE: if m.group(MOVE_COMMENT): return False mstr = m.group(MOVE) try: lmove = parseSAN(board, mstr, full=False) except ParsingError as err: notation, reason, boardfen = err.args ply = board.plyCount if ply % 2 == 0: moveno = "%d." % (ply // 2 + 1) else: moveno = "%d..." % (ply // 2 + 1) errstr1 = _( "The game can't be read to end, because of an error parsing move %(moveno)s '%(notation)s'." ) % { 'moveno': moveno, 'notation': notation } errstr2 = _("The move failed because %s.") % reason self.error = LoadingError(errstr1, errstr2) break except: ply = board.plyCount if ply % 2 == 0: moveno = "%d." % (ply // 2 + 1) else: moveno = "%d..." % (ply // 2 + 1) errstr1 = _("Error parsing move %(moveno)s %(mstr)s") % { "moveno": moveno, "mstr": mstr } self.error = LoadingError(errstr1, "") break bitboards.append(board.friends[0] | board.friends[1]) board.applyMove(lmove, full=False) movelist_append(lmove) elif group == RESULT: pass else: print("Unknown:", text) return True
def test_paresSAN1(self): """Testing parseSAN with unambiguous notations variants""" board = LBoard() board.applyFen("4k2B/8/8/8/8/8/8/B3K3 w - - 0 1") self.assertEqual(repr(Move(parseSAN(board, 'Ba1b2'))), 'a1b2') self.assertEqual(repr(Move(parseSAN(board, 'Bh8b2'))), 'h8b2') self.assertEqual(repr(Move(parseSAN(board, 'Bab2'))), 'a1b2') self.assertEqual(repr(Move(parseSAN(board, 'Bhb2'))), 'h8b2') self.assertEqual(repr(Move(parseSAN(board, 'B1b2'))), 'a1b2') self.assertEqual(repr(Move(parseSAN(board, 'B8b2'))), 'h8b2') board = LBoard() board.applyFen("4k2B/8/8/8/8/8/1b6/B3K3 w - - 0 1") self.assertEqual(repr(Move(parseSAN(board, 'Ba1xb2'))), 'a1b2') self.assertEqual(repr(Move(parseSAN(board, 'Bh8xb2'))), 'h8b2') self.assertEqual(repr(Move(parseSAN(board, 'Baxb2'))), 'a1b2') self.assertEqual(repr(Move(parseSAN(board, 'Bhxb2'))), 'h8b2') self.assertEqual(repr(Move(parseSAN(board, 'B1xb2'))), 'a1b2') self.assertEqual(repr(Move(parseSAN(board, 'B8xb2'))), 'h8b2')
def parse_movetext(self, string, board, position, variation=False): """Recursive parses a movelist part of one game. Arguments: srting - str (movelist) board - lboard (initial position) position - int (maximum ply to parse) variation- boolean (True if the string is a variation)""" boards = [] boards_append = boards.append last_board = board if variation: # this board used only to hold initial variation comments boards_append(LBoard(board.variant)) else: # initial game board boards_append(board) # status = None parenthesis = 0 v_string = "" v_last_board = None for m in re.finditer(pattern, string): group, text = m.lastindex, m.group(m.lastindex) if parenthesis > 0: v_string += ' ' + text if group == VARIATION_END: parenthesis -= 1 if parenthesis == 0: if last_board.prev is None: errstr1 = _("Error parsing %(mstr)s") % {"mstr": string} self.error = LoadingError(errstr1, "") return boards # , status v_last_board.children.append( self.parse_movetext(v_string[:-1], last_board.prev, position, variation=True)) v_string = "" continue elif group == VARIATION_START: parenthesis += 1 if parenthesis == 1: v_last_board = last_board if parenthesis == 0: if group == FULL_MOVE: if not variation: if position != -1 and last_board.plyCount >= position: break mstr = m.group(MOVE) try: lmove = parseSAN(last_board, mstr) except ParsingError as err: # TODO: save the rest as comment # last_board.children.append(string[m.start():]) notation, reason, boardfen = err.args ply = last_board.plyCount if ply % 2 == 0: moveno = "%d." % (ply // 2 + 1) else: moveno = "%d..." % (ply // 2 + 1) errstr1 = _( "The game can't be read to end, because of an error parsing move %(moveno)s '%(notation)s'.") % { 'moveno': moveno, 'notation': notation} errstr2 = _("The move failed because %s.") % reason self.error = LoadingError(errstr1, errstr2) break except: ply = last_board.plyCount if ply % 2 == 0: moveno = "%d." % (ply // 2 + 1) else: moveno = "%d..." % (ply // 2 + 1) errstr1 = _( "Error parsing move %(moveno)s %(mstr)s") % { "moveno": moveno, "mstr": mstr} self.error = LoadingError(errstr1, "") break new_board = last_board.clone() new_board.applyMove(lmove) if m.group(MOVE_COMMENT): new_board.nags.append(symbol2nag(m.group( MOVE_COMMENT))) new_board.prev = last_board # set last_board next, except starting a new variation if variation and last_board == board: boards[0].next = new_board else: last_board.next = new_board boards_append(new_board) last_board = new_board elif group == COMMENT_REST: last_board.children.append(text[1:]) elif group == COMMENT_BRACE: comm = text.replace('{\r\n', '{').replace('\r\n}', '}') comm = comm[1:-1].splitlines() comment = ' '.join([line.strip() for line in comm]) if variation and last_board == board: # initial variation comment boards[0].children.append(comment) else: last_board.children.append(comment) elif group == COMMENT_NAG: last_board.nags.append(text) # TODO elif group == RESULT: # if text == "1/2": # status = reprResult.index("1/2-1/2") # else: # status = reprResult.index(text) break else: print("Unknown:", text) return boards # , status
def parse_movetext(self, string, board, position, variation=False): """Recursive parses a movelist part of one game. Arguments: srting - str (movelist) board - lboard (initial position) position - int (maximum ply to parse) variation- boolean (True if the string is a variation)""" boards = [] boards_append = boards.append last_board = board if variation: # this board used only to hold initial variation comments boards_append(LBoard(board.variant)) else: # initial game board boards_append(board) # status = None parenthesis = 0 v_string = "" v_last_board = None for m in re.finditer(pattern, string): group, text = m.lastindex, m.group(m.lastindex) if parenthesis > 0: v_string += ' ' + text if group == VARIATION_END: parenthesis -= 1 if parenthesis == 0: if last_board.prev is None: errstr1 = _("Error parsing %(mstr)s") % {"mstr": string} self.error = LoadingError(errstr1, "") return boards # , status v_last_board.children.append( self.parse_movetext(v_string[:-1], last_board.prev, position, variation=True)) v_string = "" continue elif group == VARIATION_START: parenthesis += 1 if parenthesis == 1: v_last_board = last_board if parenthesis == 0: if group == FULL_MOVE: if not variation: if position != -1 and last_board.plyCount >= position: break mstr = m.group(MOVE) try: lmove = parseSAN(last_board, mstr) except ParsingError as err: # TODO: save the rest as comment # last_board.children.append(string[m.start():]) notation, reason, boardfen = err.args ply = last_board.plyCount if ply % 2 == 0: moveno = "%d." % (ply // 2 + 1) else: moveno = "%d..." % (ply // 2 + 1) errstr1 = _( "The game can't be read to end, because of an error parsing move %(moveno)s '%(notation)s'.") % { 'moveno': moveno, 'notation': notation} errstr2 = _("The move failed because %s.") % reason self.error = LoadingError(errstr1, errstr2) break except Exception: ply = last_board.plyCount if ply % 2 == 0: moveno = "%d." % (ply // 2 + 1) else: moveno = "%d..." % (ply // 2 + 1) errstr1 = _( "Error parsing move %(moveno)s %(mstr)s") % { "moveno": moveno, "mstr": mstr} self.error = LoadingError(errstr1, "") break new_board = last_board.clone() new_board.applyMove(lmove) if m.group(MOVE_COMMENT): new_board.nags.append(symbol2nag(m.group( MOVE_COMMENT))) new_board.prev = last_board # set last_board next, except starting a new variation if variation and last_board == board: boards[0].next = new_board else: last_board.next = new_board boards_append(new_board) last_board = new_board elif group == COMMENT_REST: last_board.children.append(text[1:]) elif group == COMMENT_BRACE: comm = text.replace('{\r\n', '{').replace('\r\n}', '}') comm = comm[1:-1].splitlines() comment = ' '.join([line.strip() for line in comm]) if variation and last_board == board: # initial variation comment boards[0].children.append(comment) else: last_board.children.append(comment) elif group == COMMENT_NAG: last_board.nags.append(text) # TODO elif group == RESULT: # if text == "1/2": # status = reprResult.index("1/2-1/2") # else: # status = reprResult.index(text) break else: print("Unknown:", text) return boards # , status
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 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()