def test_short_castling(self): legals = [ 'f5f4', 'a7a6', 'b7b6', 'c7c6', 'd7d6', 'e7e6', 'i7i6', 'j7j6', 'a7a5', 'b7b5', 'c7c5', 'e7e5', 'i7i5', 'j7j5', 'b8a6', 'b8c6', 'h6g4', 'h6i4', 'h6j5', 'h6f7', 'h6g8', 'h6i8', 'd5a2', 'd5b3', 'd5f3', 'd5c4', 'd5e4', 'd5c6', 'd5e6', 'd5f7', 'd5g8', 'j8g8', 'j8h8', 'j8i8', 'e8f7', 'c8b6', 'c8d6', 'g6g2', 'g6g3', 'g6f4', 'g6g4', 'g6h4', 'g6e5', 'g6g5', 'g6i5', 'g6a6', 'g6b6', 'g6c6', 'g6d6', 'g6e6', 'g6f6', 'g6h8', 'f8f7', 'f8g8', 'f8i8' ] moves = [ 'b2b4', 'f7f5', 'c2c3', 'g8d5', 'a2a4', 'h8g6', 'f2f3', 'i8h6', 'h2h3' ] result = sf.legal_moves("capablanca", CAPA, moves) self.assertEqual(legals, result) self.assertIn("f8i8", result) moves = [ 'a2a4', 'f7f5', 'b2b3', 'g8d5', 'b1a3', 'i8h6', 'c1a2', 'h8g6', 'c2c4' ] result = sf.legal_moves("capablanca", CAPA, moves) self.assertIn("f8i8", result) moves = [ 'f2f4', 'g7g6', 'g1d4', 'j7j6', 'h1g3', 'b8a6', 'i1h3', 'h7h6' ] result = sf.legal_moves("capablanca", CAPA, moves) self.assertIn("f1i1", result)
def test_short_castling(self): legals = [ 'f5f4', 'a7a6', 'b7b6', 'c7c6', 'd7d6', 'e7e6', 'i7i6', 'j7j6', 'a7a5', 'b7b5', 'c7c5', 'e7e5', 'i7i5', 'j7j5', 'b8a6', 'b8c6', 'h6g4', 'h6i4', 'h6j5', 'h6f7', 'h6g8', 'h6i8', 'd5a2', 'd5b3', 'd5f3', 'd5c4', 'd5e4', 'd5c6', 'd5e6', 'd5f7', 'd5g8', 'j8g8', 'j8h8', 'j8i8', 'e8f7', 'c8b6', 'c8d6', 'g6g2', 'g6g3', 'g6f4', 'g6g4', 'g6h4', 'g6e5', 'g6g5', 'g6i5', 'g6a6', 'g6b6', 'g6c6', 'g6d6', 'g6e6', 'g6f6', 'g6h8', 'f8f7', 'f8g8', 'f8i8' ] moves = [ 'b2b4', 'f7f5', 'c2c3', 'g8d5', 'a2a4', 'h8g6', 'f2f3', 'i8h6', 'h2h3' ] result = sf.legal_moves("capablanca", CAPA, moves) self.assertCountEqual(legals, result) self.assertIn("f8i8", result) moves = [ 'a2a4', 'f7f5', 'b2b3', 'g8d5', 'b1a3', 'i8h6', 'c1a2', 'h8g6', 'c2c4' ] result = sf.legal_moves("capablanca", CAPA, moves) self.assertIn("f8i8", result) moves = [ 'f2f4', 'g7g6', 'g1d4', 'j7j6', 'h1g3', 'b8a6', 'i1h3', 'h7h6' ] result = sf.legal_moves("capablanca", CAPA, moves) self.assertIn("f1i1", result) # Check that chess960 castling notation is used for otherwise ambiguous castling move # d1e1 is a normal king move, so castling has to be d1f1 result = sf.legal_moves( "diana", "rbnk1r/pppbpp/3p2/5P/PPPPPB/RBNK1R w KQkq - 2 3", []) self.assertIn("d1f1", result) # Test configurable piece perft legals = [ 'a3a4', 'b3b4', 'c3c4', 'd3d4', 'e3e4', 'f3f4', 'g3g4', 'e1e2', 'f1f2', 'b1a2', 'b1b2', 'b1c2', 'c1b2', 'c1c2', 'c1d2', 'a1a2', 'g1g2', 'd1c2', 'd1d2', 'd1e2' ] result = sf.legal_moves("yarishogi", sf.start_fen("yarishogi"), []) self.assertCountEqual(legals, result)
def test_legal_moves(self): fen = "10/10/10/10/10/k9/10/K9 w - - 0 1" result = sf.legal_moves("capablanca", fen, []) self.assertEqual(result, ["a1b1"]) result = sf.legal_moves("grand", GRAND, ["a3a5"]) self.assertIn("a10b10", result) result = sf.legal_moves("xiangqi", XIANGQI, ["h3h10"]) self.assertIn("i10h10", result) result = sf.legal_moves("xiangqi", XIANGQI, ["h3h10"]) self.assertIn("i10h10", result) result = sf.legal_moves( "shogun", SHOGUN, ["c2c4", "b8c6", "b2b4", "b7b5", "c4b5", "c6b8"]) self.assertIn("b5b6+", result) # In Janggi stalemate position pass move (in place king move) is possible fen = "4k4/c7R/9/3R1R3/9/9/9/9/9/3K5 b - - 0 1" result = sf.legal_moves("janggi", fen, []) self.assertEqual(result, ["e10e10"]) # pawn promotion of dropped pawns beyond promotion rank result = sf.legal_moves( "makhouse", "rnsmksnr/8/1ppP1ppp/p3p3/8/PPP1PPPP/8/RNSKMSNR[p] w - - 0 4", []) self.assertIn("d6d7m", result) self.assertNotIn("d6d7", result)
def is_game_end(self): with self.lock: game_end = False if self.clock_times[(len(self.moves) - 1) % 2] <= 0: # time loss logging.warning('Engine {} loses on time.'.format((len(self.moves) - 1) % 2 + 1)) result = 1 game_end = True elif self.moves and not self.is_legal(): # last move was illegal result = 1 game_end = True logging.error('Illegal move: {}'.format(self.moves[-1])) elif not sf.legal_moves(self.variant, self.get_start_fen(), self.moves): game_end = True result = sf.game_result(self.variant, self.get_start_fen(), self.moves) else: game_end, result = sf.is_optional_game_end(self.variant, self.get_start_fen(), self.moves) if game_end: self.result = int(math.copysign(1, result if len(self.moves) % 2 == 0 else -result)) if result else result return game_end
def test_legal_moves(self): fen = "10/10/10/10/10/k9/10/K9 w - - 0 1" result = sf.legal_moves("capablanca", fen, []) self.assertEqual(result, ["a1b1"]) result = sf.legal_moves("grand", GRAND, ["a3a5"]) self.assertIn("a10b10", result) result = sf.legal_moves("xiangqi", XIANGQI, ["h3h10"]) self.assertIn("i10h10", result) result = sf.legal_moves("xiangqi", XIANGQI, ["h3h10"]) self.assertIn("i10h10", result) result = sf.legal_moves("shogun", SHOGUN, ["c2c4", "b8c6", "b2b4", "b7b5", "c4b5", "c6b8"]) self.assertIn("b5b6+", result) # In Janggi stalemate position pass move (in place king move) is possible fen = "4k4/c7R/9/3R1R3/9/9/9/9/9/3K5 b - - 0 1" result = sf.legal_moves("janggi", fen, []) self.assertEqual(result, ["e10e10"])
def legal_moves(self): # move legality can depend on history, e.g., passing and bikjang return sf.legal_moves(self.variant, self.initial_fen, self.move_stack, self.chess960)
def legal_moves(self): # print("FEN, vaiant, self.move_stack:", self.variant, self.initial_fen, self.move_stack) legals = sf.legal_moves(self.variant, self.fen, [], self.chess960) # print(" legal_moves:", legals) return legals
def get_actions(self, color): moves = pyffish.legal_moves("janggi", self.initial_fen, self.previous_moves) return [Action.from_uci_usi(move) for move in moves]
def runMatches(self, variant: Variant, matchCount=100, debug=False, variantPath: str = "") -> MatchData: """ :param variant: The variant we want to run matches of. :param matchCount: The number of matches to run :param debug: If true, print debug statements :param variantPath: A path to the .ini file that contains the variant. If none is provided, one will be created. :return: """ matchData = MatchData(variant) if variantPath == "" and not variant.builtIn: variantPath = "variant-{0}.ini".format(variant.name) with open(variantPath, "w") as ini: ini.write(variant.getFairyStockfishINI()) pyffish.set_option("VariantPath", variantPath) for e in self.engines: # Set the engines to the variant we are running. e.setVariant(variant, variantPath) # This is the root of our MCT for matchNo in range(matchCount): match = Match(variant, (matchNo + 1)) for e in self.engines: e.newgame() # Go through a MCTS opening stop = False curNode: MonteCarloTreeNode = matchData.MCTRoot while not stop: match.curNode = curNode stop, curNode = curNode.selectBestChild() if curNode is None: # Checkmate or stalemate. if pyffish.game_result(variant.name, variant.startingFEN, match.moves) == 0: # Stalemate match.markDraw() elif i % 2 == 0: match.markBlackVictory() else: match.markWhiteVictory() break move = curNode.move match.addMove(move) # This is the loop that goes through the moves in any individual game while True: # Don't let too many moves happen! if len(match.moves) >= 1000: match.markDraw() break legal_moves = pyffish.legal_moves(variant.name, variant.startingFEN, match.moves) if len(legal_moves) == 0 and pyffish.game_result( variant.name, variant.startingFEN, match.moves) == 0: match.markDraw() break elif pyffish.is_optional_game_end(variant.name, variant.startingFEN, match.moves)[0]: match.markDraw() break active_engine = self.engines[len(match.moves) % 2] inactive_engine = self.engines[(len(match.moves) + 1) % 2] active_engine.setposition(match.moves) moveDict = active_engine.bestmove() bestMove: str = moveDict["move"] ponder: str = moveDict["ponder"] info: str = moveDict["info"] match.addMove(bestMove) if debug: print("{0}, move {1}, info {2}".format( len(match.moves), bestMove, info)) # If the engine found mate, then we can stop running through the steps. # TODO: This needs to be replaced with calls to pyffish. if 'mate' in moveDict.keys(): mateNum: int = moveDict['mate'] if mateNum in (1, 0): # Somebody has checkmate, so find out who is the winner if mateNum > 0: winning = active_engine else: winning = inactive_engine if winning == self.whiteEngine: match.markWhiteVictory() else: match.markBlackVictory() break # Add the matches we just played to the match data. matchData.addMatch(match) print(match) return matchData
def is_legal(self): assert self.moves return self.moves[-1] in sf.legal_moves(self.variant, self.get_start_fen(), self.moves[:-1])