为了账号安全,请及时绑定邮箱和手机立即绑定

使用 io.WriteString 时可执行文件提前退出

使用 io.WriteString 时可执行文件提前退出

Go
慕森卡 2022-10-10 15:42:31
我正在使用 io 包来处理我的 PATH 中定义的可执行文件。可执行文件称为“Stockfish”(国际象棋引擎),显然可以通过命令行工具使用。为了让引擎搜索最佳移动,您使用“go depth n” - 深度越高 - 搜索所需的时间越长。使用我的命令行工具,它使用 20 的深度搜索大约 5 秒,它看起来像这样:go depth 20info string NNUE evaluation using nn-3475407dc199.nnue enabledinfo depth 1 seldepth 1 multipv 1 score cp -161 nodes 26 nps 3714 tbhits 0 time 7 pv e7e6info depth 2 seldepth 2 multipv 1 score cp -161 nodes 51 nps 6375 tbhits 0 time 8 pv e7e6 f1d3info depth 3 seldepth 3 multipv 1 score cp -161 nodes 79 nps 7900 tbhits 0 time 10 pv e7e6 f1d3 g8f6info depth 4 seldepth 4 multipv 1 score cp -161 nodes 113 nps 9416 tbhits 0 time 12 pv e7e6 f1d3 g8f6 b1c3[...]bestmove e7e6 ponder h2h4现在,使用 io.WriteString 它在毫秒后完成,没有任何(可见)计算:(这也是下面代码的输出)Stockfish 14 by the Stockfish developers (see AUTHORS file)info string NNUE evaluation using nn-3475407dc199.nnue enabledbestmove b6b5这是我使用的代码:func useStockfish(commands []string) string {    cmd := exec.Command("stockfish")    stdin, err := cmd.StdinPipe()    if err != nil {        log.Fatal(err)    }    for _, cmd := range commands {        writeString(cmd, stdin)    }    err = stdin.Close()    if err != nil {        log.Fatal(err)    }    out, err := cmd.CombinedOutput()    if err != nil {        log.Fatal(err)    }    return string(out)}func writeString(cmd string, stdin io.WriteCloser) {    _, err := io.WriteString(stdin, cmd)    if err != nil {        log.Fatal(err)    }这是我如何使用它的一个例子。第一个命令是设置位置,第二个是计算深度为 20 的下一个最佳移动。结果如上所示。func FetchComputerMove(game *internal.Game) {    useStockfish([]string{"position exmaplepos\n", "go depth 20"})}
查看完整描述

1 回答

?
心有法竹

TA贡献1866条经验 获得超5个赞

要利用引擎stockfish,您需要启动流程并保持运行。


您正在执行它,通过标准输入管道传递 2 个命令,然后关闭管道。关闭管道向程序表明您不再对引擎所说的内容感兴趣。


要运行它 - 并保持它运行 - 你需要类似的东西:


func startEngine(enginePath string) (stdin io.WriteCloser, stdout io.ReadCloser, err error) {

    cmd := exec.Command(enginePath )


    stdin, err = cmd.StdinPipe()

    if err != nil {

        return

    }

    stdout, err = cmd.StdoutPipe()

    if err != nil {

        return

    }


    err = cmd.Start() // start command - but don't wait for it to complete

    return

}

返回的管道允许您发送命令并实时查看输出:


stdin, stdout, err := startEngine("/usr/local/bin/stockfish")



sendCmd := func(cmd string) error {

    _, err := stdin.Write([]byte(cmd + "\n"))

    return err

}


sendCmd("position examplepos")

sendCmd("go depth 20")

然后粗略地读取异步响应:


b := make([]byte, 10240)


for {

    n, err := stdout.Read(b)

    if err != nil {

        log.Fatalf("read error: %v", err)

    }

    log.Println(string(b[:n]))

}

一旦bestmove d2d4 ponder g8f6出现like 行,就知道当前的分析命令已经完成。


如果这就是您所需要的,您可以关闭引擎(通过关闭stdin管道),或者保持打开状态以进一步提交命令。


查看完整回答
反对 回复 2022-10-10
  • 1 回答
  • 0 关注
  • 145 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号