{stockfish}
é um pacote R que implementa o protocolo aberto de comunicação
UCI e acompanha uma
instalação do Stockfish 11,
um motor de xadrez muito popular, open source e poderoso escrito em C++.
Instalação
install.packages("stockfish")
Ou instale a versão em desenvolvimento do GitHub com:
# install.packages("remotes")
remotes::install_github("curso-r/stockfish")
Você também pode encontrar mais (e mais recentes) versões do motor Stockfish
para usar com o {stockfish}
na
página de download do projeto.
Exemplo
É tão fácil usar o {stockfish}
quanto qualquer outro pacote UCI. Você deve
inicializar o motor com fish$new()
e enviar comandos com os seus métodos
internos, lembrando apenas de rodar quit()
quando você terminar.
library(stockfish)
# Inicializar o motor
engine <- fish$new()
# Examinar o processo em plano de fundo
engine$process
#> PROCESS 'stockfish', running, pid 173670.
# Procurar a melhor jogada
engine$go()
#> [1] "bestmove e2e4 ponder d7d5"
# Começar um jogo a partir de um FEN
engine$ucinewgame()
engine$position("6rk/2Q3p1/5qBp/5P2/8/7P/6PK/8 w - - 15 51")
engine$go()
#> [1] "bestmove g6f7 ponder g8d8"
# Finalizar o motor
engine$quit()
Uso
fish
, a principal classe do pacote, representa um motor Stockfish, permitindo
que o usuário envie comandos e receba saídas de acordo com o protocolo UCI.
Resumindo, um objeto fish
, quando criado, cria um processo Stockfish
desacoplado e faz um pipe com as suas entrada e saída padrões.
Para mais informações, veja a sua documentação completa executando ?fish
.
Stockfish Incluso
O pacote acompanha uma instalação do Stockfish, um motor de xadrez muito popular, open source e poderoso escrito em C++. Ele consegue chegar em um ELO de 3516, roda no Windows, macOS, Linux, iOS e Android, e pode ser compilado em menos de um minuto.
Quando o {stockfish}
(inicial minúscula) estiver sendo instalado, o
código-fonte do Stockfish (inicial maiúscula) é compilado e o executável
resultante é armazenado junto com os seus pacote R. Isso não é uma instalação
para todos os usuários! Você não precisa dar privilégios administrativos para
ele rodar ou se preocupar com qualquer software adicional.
O único ponto negativo é que a versão inclusa é o Stockfish 11, não a versão
mais recente (Stockfish 12). Isso ocorre porque a versão 12 precisa de downloads
adicionais, o que aumentaria dramaticamente o tempo de instalação. Se quiser,
você pode baixar a versão de sua escolha
e passar o caminho para o executável como argumento para fish$new()
.
Protocolo UCI
UCI (Universal Chess Interface) é um protocolo aberto de comunicação que
permite que motores de xadrez se comuniquem com interfaces de usuário. Na
verdade, a classe fish
implementa o
protocolo UCI como publicado
por Stefan-Meyer Kahlen, apenas com um foco no Stockfish. Isso significa que
alguns métodos não são implementados (veja Pegadinhas) e que todos os testes
são feitos com o Stockfish, mas todo o resto deveria funcionar perfeitamente com
outros motores.
O texto entre aspas no fim da documentação de cada método foi extraído diretamente do protocolo UCI oficial para que você possa ver exatamente o que aquele comando pode fazer. No geral, os comandos são bem autoexplicativos, exceto pela LAN (long algebraic notation), a notação de jogadas usada pelo UCI. Nessa notação, jogadas são registradas usando as posições inicial e final da peça, por exemplo, e2e4, e7e5, e1g1 (roque pequeno das brancas), e7e8q (promoção), 0000 (jogada vazia).
Implementação
Todo o trabalho duro da classe fish
é feito pelo pacote {processx}
. O
processo do Stockfish é criado com processx::process$new
e a entrada/saída é
feita com write_input()
e read_output()
. Um aspecto importante do protocolo
de comunicação de qualquer motor UCI é esperar por respostas, e aqui isso é
feito com um loop que verifica o processo com poll_io()
e para assim que a
saída volta vazia.
Antes de implementar o protocolo UCI manualmente, o pacote usava o {bigchess}
.
Ele é um pacote incrível criado por
@rosawojciech, mas ele tem algumas
dependências que estão além do escopo do {stockfish}
e, no final, eu queria
mais controle da API (por exemplo usando {R6}
).
Pegadinhas
A classe fish
tem algumas idiossincrasias que o usuário deve ter em mente
quando tentar se comunicar com o Stockfish. Algumas são devidas a escolhas de
implementação, mas outras estão relacionadas ao protocolo UCI em si. Esta não
é uma lista completa (e você provavelmente deveria ler a
documentação do UCI), mas
aqui vão algumas coisas para ficar de olho.
Nem todos os métodos UCI foram implementados: como o
{stockfish}
foi feito com o Stockfish (e especialmente o Stockfish 11) em mente, dois métodos do UCI que não funcionam com o motor não foram implementados. Eles sãodebug()
eregister()
.A maioria dos métodos retorna silenciosamente: como a maioria dos comandos UCI não retornam nada ou retornam texto padrão, a maioria dos métodos retorna silenciosamente. As exceções são
run()
,isready()
,go()
estop()
; você pode ver exatamente o que eles retornam lendo as suas documentações.Nem toda opção do Stockfish vai funcionar: pelo menos quando usando a versão inclusa do Stockfish, nem todas as opções documentadas vão funcionar com
setoption()
. Isso ocorre porque, como descrito acima, o pacote vem com o Stockfish 11, que não é a versão mais recente. Opções que não vão funcionar estão marcadas com um asterisco.Tempos são em milissegundos. diferentemente da maioria das funções do R, todo método que recebe um intervalo de tempo espera que o mesmo seja em milissegundos, não segundos.