def test_game_result(self): result = sf.game_result("chess", CHESS, ["f2f3", "e7e5", "g2g4", "d8h4"]) self.assertEqual(result, -sf.VALUE_MATE) # shogi pawn drop mate result = sf.game_result("shogi", "lnsg3nk/1r2b1gs1/ppppppp1p/7N1/7p1/9/PPPPPPPP1/1B5R1/LNSGKGS1L[P] w 0 1", ["P@i8"]) self.assertEqual(result, sf.VALUE_MATE) # losers checkmate result = sf.game_result("losers", CHESS, ["f2f3", "e7e5", "g2g4", "d8h4"]) self.assertEqual(result, sf.VALUE_MATE) # suicide stalemate result = sf.game_result("suicide", "8/8/8/7p/7P/8/8/8 w - - 0 1", []) self.assertEqual(result, sf.VALUE_DRAW) result = sf.game_result("suicide", "8/8/8/7p/7P/7P/8/8 w - - 0 1", []) self.assertEqual(result, -sf.VALUE_MATE) result = sf.game_result("suicide", "8/8/8/7p/7P/8/8/n7 w - - 0 1", []) self.assertEqual(result, sf.VALUE_MATE) # atomic check- and stalemate # checkmate result = sf.game_result("atomic", "BQ6/Rk6/8/8/8/8/8/4K3 b - - 0 1", []) self.assertEqual(result, -sf.VALUE_MATE) # stalemate result = sf.game_result("atomic", "KQ6/Rk6/2B5/8/8/8/8/8 b - - 0 1", []) self.assertEqual(result, sf.VALUE_DRAW)
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 game_result(self): return sf.game_result(self.variant, self.initial_fen, self.move_stack, self.chess960)
def test_game_result(self): result = sf.game_result("chess", CHESS, ["f2f3", "e7e5", "g2g4", "d8h4"]) self.assertTrue(result < 0)
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