iOS集成ChessKitEngine时Stockfish NNUE文件加载失败求助
使用ChessKitEngine集成Stockfish时NNUE文件加载失败问题
背景
我正在使用ChessKitEngine将Stockfish集成到iOS应用中,已将从Stockfish官网下载的nn-1111cefa1111.nnue文件添加到项目根目录并纳入编译目标,未修改文件名。
问题
无论如何指定NNUE文件(仅文件名、完整路径、转义空格等),引擎均无法加载该文件并崩溃。
我的代码
import Foundation import ChessKitEngine final class StockfishEngine { static let shared = StockfishEngine() private let engine = Engine(type: .stockfish) private var isReady = false private var pendingCompletionHandlers: [(String?) -> Void] = [] init() { startEngine() } func startEngine() { print("Starting engine initialization...") engine.loggingEnabled = true engine.start { self.engine.send(command: .uci) // 尝试设置NNUE文件 self.engine.send(command: .setoption(id: "EvalFile", value: "nn-1111cefa1111.nnue")) let threadCount = min(ProcessInfo.processInfo.processorCount - 1, 7) self.engine.send(command: .setoption(id: "Threads", value: String(threadCount))) self.engine.send(command: .setoption(id: "Skill Level", value: "10")) self.engine.send(command: .isready) self.engine.receiveResponse = { response in if "\(response)".contains("readyok") { self.isReady = true print("Stockfish Engine Started!") self.processPendingRequests() self.setupMoveResponseHandler() } } } } }
错误日志
Starting engine initialization... uci Stockfish 17 by the Stockfish developers (see AUTHORS file) minemine x <id> <name> Stockfish 17 <id> <author> the Stockfish developers (see AUTHORS file) option name Debug Log File type string default <empty> option name Clear Hash type button option name Ponder type check default false option name EvalFile type string default nn-1111cefa1111.nnue option name EvalFileSmall type string default nn-37f18f62d772.nnue <uciok> isready <readyok> setoption name EvalFile value /Users/myname/Library/Developer/CoreSimulator/Devices/D1F042AC-7361-4EBC-86B7-6FA9050F68A9/data/Containers/Bundle/Application/885F453B-3219-475A-9786-14C7DF2BFBB1/App%20Name.app/nn-1111cefa1111.nnue setoption name Threads value 7 setoption name MultiPV value 1 uci setoption name EvalFile value nn-1111cefa1111.nnue setoption name Threads value 7 setoption name Skill Level value 10 isready Stockfish Engine Started! <info> <string> Using 7 threads <id> <name> Stockfish 17 <id> <author> the Stockfish developers (see AUTHORS file) option name Debug Log File type string default <empty> option name EvalFile type string default nn-1111cefa1111.nnue option name EvalFileSmall type string default nn-37f18f62d772.nnue <uciok> <info> <string> Using 7 threads <readyok> setoption name Skill Level value 0 ucinewgame position fen rnbqkbnr/pppppppp/8/8/8/3P4/PPP1PPPP/RNBQKBNR b KQkq - 0 1 go depth 15 rnbqkbnr/pppppppp/8/8/8/3P4/PPP1PPPP/RNBQKBNR b KQkq - 0 1 <info> <string> Available processors: 0-7 <info> <string> Using 7 threads <info> <string> ERROR: Network evaluation parameters compatible with the engine must be available. <info> <string> ERROR: The network file nn-1111cefa1111.nnue was not loaded successfully. <info> <string> ERROR: The UCI option EvalFile might need to specify the full path, including the directory name, to the network file. <info> <string> ERROR: The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/nn-1111cefa1111.nnue <info> <string> ERROR: The engine will be terminated now.
已尝试方案
- 指定仅文件名:
"nn-1111cefa1111.nnue" - 使用完整路径:
let path = Bundle.main.path(forResource: "nn-1111cefa1111", ofType: "nnue") self.engine.send(command: .setoption(id: "EvalFile", value: path ?? "")) - 转义路径中的空格
- 验证文件已存在于应用包内
解决方案
1. 确认NNUE文件与Stockfish版本匹配
你使用的是Stockfish 17,必须确保下载的nn-1111cefa1111.nnue是对应Stockfish 17的版本,版本不匹配会直接导致加载失败。
2. 修正UCI命令发送顺序
UCI协议要求必须在收到<uciok>响应后才能设置引擎选项,你的代码在发送.uci后立刻发送setoption,违反了协议流程。调整代码逻辑:
func startEngine() { print("Starting engine initialization...") engine.loggingEnabled = true engine.start { self.engine.send(command: .uci) self.engine.receiveResponse = { response in let responseStr = "\(response)" // 先处理uciok响应,再设置选项 if responseStr.contains("<uciok>") { // 获取应用包内NNUE文件的正确路径 if let nnuePath = Bundle.main.path(forResource: "nn-1111cefa1111", ofType: "nnue") { self.engine.send(command: .setoption(id: "EvalFile", value: nnuePath)) } let threadCount = min(ProcessInfo.processInfo.processorCount - 1, 7) self.engine.send(command: .setoption(id: "Threads", value: String(threadCount))) self.engine.send(command: .setoption(id: "Skill Level", value: "10")) self.engine.send(command: .isready) } else if responseStr.contains("readyok") { self.isReady = true print("Stockfish Engine Started!") self.processPendingRequests() self.setupMoveResponseHandler() } } } }
3. 检查文件的打包配置
- 在Xcode中选中nnue文件,确认Target Membership已勾选你的应用目标。
- 进入项目的Build Phases,检查Copy Bundle Resources列表中是否包含该nnue文件,确保它会被打包到应用包内。
4. 避免重复发送命令
从错误日志可以看到,代码重复发送了uci和setoption命令,导致引擎状态混乱。确保命令只发送一次,流程逻辑清晰。
内容的提问来源于stack exchange,提问作者Avadhesh18
相关产品推荐
相关产品推荐

