Php proc_open() 和 stockfish 国际象棋引擎异常深度 1

Php proc_open() and stockfish chess engine anomaly depth 1

期待将 stockfish chess engine 集成到 php-cli 脚本中。

有一个意外的行为,stockfish程序没有"thinking"就直接退出了,它return只有深度1的位置,当从php调用时。

为了更好地理解,在从命令行 运行 运行 stockfish 程序时,这里是预期的行为 (gif):


从php开始,以下是有效的(起始位置,白棋,要求50深度),它 return 是一步 a2a3,深度 1 的位置,这是一个非常糟糕的一步!

答案是即时的,通过所有深度级别至少需要很多秒。

它与任何 FEN positions 相同,总是 return 深度 1。

$descr = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
);
$pipes = array();
$process = proc_open("stockfish", $descr, $pipes);
if (is_resource($process)) {
    fwrite($pipes[0], "uci\n");
    fwrite($pipes[0], "ucinewgame\n");
    fwrite($pipes[0], "position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - - 0 1\n");    
    fwrite($pipes[0], "go depth 50\n");
    fclose($pipes[0]);    
    // Read all output from the pipe
    while (!feof($pipes[1])) {    
        echo fgets($pipes[1]);
    }
    fclose($pipes[1]);
    proc_close($process);

}
// RETURN last line:  bestmove a2a3

stockfish的所有版本都已测试,8、9、10,结果相同。

我尝试了很多选项和不同的方法来从 php 运行 shell 命令,包括 posix_mkfifo() 管道,但是 none 正在按预期工作,总是 return 在深度 1 移动。

另一个例子,同样的行为,return总是"a2a3"。

  file_put_contents(".COMFISH","uci\nucinewgame\nsetoption name Threads value 1\nposition fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - - 0 1\ngo depth 50");
  $COM = explode(" ",system("stockfish < .COMFISH"))[1];
  var_dump($COM);
  // RETURN a2a3

这可能直接链接到 stockfish 二进制文件的编写方式(多线程),而不是 php 行为,但我在这里寻找解释?

来自 wiki:

Stockfish can use up to 512 CPU threads in multiprocessor systems.

好吧,这相当简单,管道关闭得太早了。

为未来的读者留下工作代码的基础。

$descr = [0 => ["pipe", "r"], 1 => ["pipe", "w"]];
$pipes = [];
$process = proc_open("stockfish", $descr, $pipes);
if (is_resource($process)) {
    fwrite($pipes[0], "uci\n");
    fwrite($pipes[0], "ucinewgame\n");
    fwrite($pipes[0], "position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - - 0 1\n");    
    fwrite($pipes[0], "setoption name Skill Level value 17\n"); // Set level between 1 and 20
    fwrite($pipes[0], "go movetime 5000\n"); // Return bestmove after 5 seconds          
    while (!feof($pipes[1])) {    
        echo fgets($pipes[1]);
    }
    fclose($pipes[0]);
    fclose($pipes[1]);
    proc_close($process);    
}
// RETURN last line: bestmove e2e4 ponder e7e6