Italian B4A: come implementare un'interfaccia per motori scacchistici UCI?

Stolcius Von Stolcenberg

Member
Licensed User
Ecco la mia configurazione AVD:
View attachment 54398

ma ti conviene includere la libreria per x86 (se c'è nel progetto originale) così usi l'emulatore x86 (HW accelerated).

In ogni caso, dovresti includere tutte le librerie nel tuo progetto e poi codice che va a stabilire l'architettura e poi chiami quella corretta.
Grazier Giga!

Trattasi della conf che riesce a intercettare l'output dell'engine, no?
 

Stolcius Von Stolcenberg

Member
Licensed User
Cmq, per curiosità ho provato a non inviare il comando chmod, per vedere se alla fine il file avesse gli stessi permessi e quindi il comando non avesse avuto alcun effetto e invece... senza non ha tutti i permessi, il che significa che il comando è stato eseguito, malgrato il dispositivo non sia rootato e l'app non abbia i permessi di root. Questo mi meraviglia non poco.

Tieni comunque presente che il chmod funziona solo dentro il package(I hope). Se provi a cambiare le permission "ad manellam" con una shell ricevi un secco "permission denied"
 

LucaMs

Expert
Licensed User
Longtime User
In ogni caso, dovresti includere tutte le librerie nel tuo progetto e poi codice che va a stabilire l'architettura e poi chiami quella corretta.
Non ne so un tubo (tanto è vero che chiesi a @MarcoRome di creare un bel tutorial in italiano, ma è pigro e mi ha solo sparato dei link :p)... quei due file (provati entrambi su dispositivo reale e nada), stockfish-8-arm64-v8a e stockfish-8-armeabi-v7a, di che razza sono? Unzippati comprendono 8 file, anch'essi non so di che tipo.

Cmq, se sull'emulatore di @moster67 funge...! (guardando il codice Java manco capisco come vada in esecuzione il motore, ma non datemi retta, prima o poi studierò :D)
 

moster67

Expert
Licensed User
Longtime User
Grazier Giga!

Trattasi della conf che riesce a intercettare l'output dell'engine, no?

v. questo (i commenti con Aggiunto)

B4X:
#if Java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.*;
import java.util.*;
import java.util.Comparator;
import android.annotation.SuppressLint;
import android.os.Environment;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.keywords.Common;
import android.os.Build; //aggiunto

private BufferedReader processReader;
private OutputStreamWriter processWriter;
private Process engineProcess;



public String startUciEngine(String fileFullPath) {
   StringBuilder sb = new StringBuilder();

   anywheresoftware.b4a.BA.Log("Cpu is: " + Build.CPU_ABI); //agguinto
 
   Common.Log("STARTING ENGINE..." );
   try {
      
        String[] args ={fileFullPath};
      
        engineProcess = Runtime.getRuntime().exec(args);
      
         processReader = new BufferedReader(
                            new InputStreamReader(engineProcess.getInputStream()));
     
        boolean exitCondition= false;
        String line = "";
        while (!exitCondition) {
          
            if((line=processReader.readLine())!=null){
                sb.append(line + "\n");
             }
            if(!processReader.ready()){
               exitCondition = true;
            }           
         }
      
   } catch (Exception e) {
        
           Common.Log("ERRORE" + e);
   }
        return sb.toString();
}
#End If
 

LucaMs

Expert
Licensed User
Longtime User
A me non funziona né:

1) dispositivo, con arm64
2) dispositivo, con armeabi
3) emulatore con arm64 (emulatore GenyMotion, sul quale l'unica impostazione "utile" è quella del processore, c'era Centrino Intel ed ho lasciato quella)

Cmq, come mai funziona sull'emulatore di @moster67 ma non sul suo dispositivo reale? Questo è il dilemma! Lo sapremo... prima o poi :)
 

moster67

Expert
Licensed User
Longtime User
Potresti usare questo sub:
B4X:
Sub LoadEngine()

    Dim CPU As String = jo.RunMethod("GetCPU",Null)
    Log("CPU is >> " & CPU)
  
    If CPU = "armeabi-v7a" Then
        File.Copy(File.DirAssets,EngineFileName, EngineDir, "stockfish-8-armeabi-v7a")
    else if CPU = "arm64-v8a" Then
        File.Copy(File.DirAssets,EngineFileName, EngineDir, "stockfish-8-arm64-v8a")
    Else 'per esempio x86
        Log ("your CPU is not supported")
        'do something
    End If
    ShellCommand("chmod 777")
    ShowFileProperties
End Sub

chiamando il metodo GetCPU che ho aggiunto nel tuo codice Java qui sotto:
B4X:
#if Java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.*;
import java.util.*;
import java.util.Comparator;
import android.annotation.SuppressLint;
import android.os.Environment;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.keywords.Common;
import android.os.Build; //aggiunto

private BufferedReader processReader;
private OutputStreamWriter processWriter;
private Process engineProcess;


     public String GetCPU(){
        //anywheresoftware.b4a.BA.Log("Cpu is: " + Build.CPU_ABI); //agguinto
        return Build.CPU_ABI;
    }



public String startUciEngine(String fileFullPath) {
   StringBuilder sb = new StringBuilder();

 

 
   Common.Log("STARTING ENGINE..." );
   try {
      
        String[] args ={fileFullPath};
      
        engineProcess = Runtime.getRuntime().exec(args);
      
         processReader = new BufferedReader(
                            new InputStreamReader(engineProcess.getInputStream()));
     
        boolean exitCondition= false;
        String line = "";
        while (!exitCondition) {
          
            if((line=processReader.readLine())!=null){
                sb.append(line + "\n");
             }
            if(!processReader.ready()){
               exitCondition = true;
            }           
         }
      
   } catch (Exception e) {
        
           Common.Log("ERRORE" + e);
   }
        return sb.toString();
}
#End If

Se nel progetto includi le 2 librerie "stockfish-8-armeabi-v7a" e "stockfish-8-arm64-v8a", il tuo progetto dovrebbe funzionare sui tutti i device/emulatori che sono compatibili. Se non è compatibile gestisci l'errore.

Ps: forse devi cambiare altre cose nel tuo progetto - non ho controllato bene
 

moster67

Expert
Licensed User
Longtime User
Sono librerie native (*.so) e compilati specificamente per l'architettura tipo x86, arm, mips. Non sono lib jar.
 

Stolcius Von Stolcenberg

Member
Licensed User
Potresti usare questo sub:

Se nel progetto includi le 2 librerie "stockfish-8-armeabi-v7a" e "stockfish-8-arm64-v8a", il tuo progetto dovrebbe funzionare sui tutti i device/emulatori che sono compatibili. Se non è compatibile gestisci l'errore.

Grazie tera, moster: ottima dritta :)

Di fatto, i due file non dovrebbero essere delle librerie, ma degli ELF (Executable and Linkable Format) file.

Ps: forse devi cambiare altre cose nel tuo progetto - non ho controllato bene

Sicuramente ancora c'è molto da fare, in questo senso.

  • bisogna sviluppare la logica che invia i comandi alla pipe
  • il tutto va inserito in un thread per rendere asincrono il flusso di output del processo relativo all'engine
  • e molto altro...
Per i primi due punti, però, ho già le idee chiare... :)

Per chi voglia comprendere meglio come dovrebbe funzionare un engine uci, consiglio di scaricare la versione per windows(sempre da https://stockfishchess.org/download/), lanciarla è imputare il comando uci "go"(img Cattura 1-3 in allegato).
Alla fine dell'elaborazione il motore restituirà la mossa migliore(lato bianco) "bestmove d2d4" e la previsione per il nero "d7d5".

In soldoni le funzioni che andranno implementate dovranno permettere questo tipo di comunicazione.

Un salutone,
Stolcius
 

Attachments

  • Cattura1.JPG
    Cattura1.JPG
    29.7 KB · Views: 203
  • Cattura2.JPG
    Cattura2.JPG
    27.2 KB · Views: 202
  • Cattura3.JPG
    Cattura3.JPG
    68.4 KB · Views: 204

moster67

Expert
Licensed User
Longtime User
i due file non dovrebbero essere delle librerie, ma degli ELF (Executable and Linkable Format) file.
Secondo me sono così dette "shared libraries". Per curiosità ho aggiunto l'estensione .so alla libreria e tutto funziona tranquillamente.
Android, almeno per quello che so io, usa librerie "ELF .so" per il Java Native Interface. Probabilmente il tuo codice in java con il metodo "Runtime.getRuntime().exec(args);" esegue a sua volta "System.loadLibrary".

Con Android Runtime (ART), introdotto con Lollipop, tutte le applicazioni vengono compilati nel formato binario ELF durante l'installazione.
 
Top