3

I downloaded the binary of Android Stockfish arm64-v8a and looked in the CPP source files. In main() there is all initialization, and then there is UCI::loop(), which catches standard input with getline() and writes back with sync_cout(). How can I write to the engine from a c# (xamarin) application? And is it necessary to make some additional initialization?

I found this, which could be close to my problem, but maybe it is not. I don't want to spend three days just to see I'm doing complete nonsense.

Also I don't know how to recognize Stockfish's console. Is there only one console, no matter how many different libraries the program can use?

As I don't understand the technical part much, I'm including a screenshot of what I expect to be the Stockfish I should communicate with :-). If it is wrong from the beginning, please let me know.

enter image description here

EDIT: What file type is the stockfish-8-arm64-v8a, is it android native library or native shell executable or something else? Where to put the file, how to set it up (in Visual Studio 2015), how to call it from code? I have some code that I tried here but still I can't make it work.

1
  • 1
    Have you tried changing "Copy to Output Directory" to "Copy" instead of "Do not copy"? That's a common "gotcha" in Visual Studio. Then you can use relative file paths to reference the exe
    – Andrew
    Jun 2, 2017 at 5:50

3 Answers 3

3

When you're using C#, you can use any UCI engine in the same manner. With C# you have to add an event handler to the OutputDataReceived event (and optionally the ErrorDataReceived event). As a quick example:

ProcessStartInfo si = new ProcessStartInfo() {
    FileName = uciPath,
    UseShellExecute = false,
    CreateNoWindow = true,
    RedirectStandardError = true,
    RedirectStandardInput = true,
    RedirectStandardOutput = true
};

myProcess = new Process();
myProcess.StartInfo = si;
try {
    // throws an exception on win98
    myProcess.PriorityClass = ProcessPriorityClass.BelowNormal;
} catch { }

myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);

myProcess.Start();
myProcess.BeginErrorReadLine();
myProcess.BeginOutputReadLine();

SendLine("uci");
SendLine("isready");
SendLine("ucinewgame");

And the methods alluded to above:

    private void SendLine(string command) {
        myProcess.StandardInput.WriteLine(command);
        myProcess.StandardInput.Flush();
    }

    private void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) {
        string text = e.Data;
        //Debug.WriteLine("[UCI] " + text);
    }

This is an incredibly simplified example. In my own code I have a semaphore in order to fully process each output line before moving on to the next one and several semaphores in the UCI start and "isready" handling.

For a full overview of the UCI protocol, check out the specification.

3
  • I think the OP is asking about his "missing file" problem. Look at the comment he posted to my answer.
    – ABCD
    Jun 2, 2017 at 5:34
  • @SmallChess yes, looks like that is the biggest issue - I didn't see a way for the OP to actually capture the output so I figured I would add the code snippet anyways. Cheers!
    – Andrew
    Jun 2, 2017 at 5:37
  • Hey! I have tried your code with Debug.WriteLine() and Console.WriteLine() but I do not receive any information back from the engine. How to solve this? Thanks! May 31, 2018 at 20:22
2
+100

You're using the compiled Stockfish binary so you don't need to worry anything about C++. You only need to think about C++ if you're compiling the Stockfish source code yourself (but you're not).

The link you have is about calling a DLL in C# - this has nothing to what you want to do. The Stockfish program you have is independently compiled, and has nothing to do with Microsoft's DLL implementation.

You're looking for this:

https://stackoverflow.com/questions/4291912/process-start-how-to-get-the-output

You should start a new engine process, run it and communicate with the engine by UCI protocol.

EDIT:

I see you have started +100 bounty, but I think it's a mistake. I believe my answer is accurate but I'm unable to debug your environment. Your problem is the unknown file path. Have you added a text file, and try to read it in your app? If you can't load a text file in your program, you can't start a chess engine. Please give a go.

  • Save a new text file to where you have the Stockfish engine
  • Try to read the text file
  • You may want to do it on a simulator. On your PC simulator, you can use path like C:\Engine\SF_engine.

Your technical difficulty has nothing to do with chess engine or UCI protocol, and thus off-topic here.

4
  • I tried that and still fighting with the technical part. If you could please look at this question: stackoverflow.com/questions/44267734/…
    – hoacin
    May 31, 2017 at 4:50
  • @hoacin Try full path?
    – ABCD
    May 31, 2017 at 4:51
  • When I look at file properties, it is located on PC somewhere in project folder. It doesn't work, PC folder shouldn't work from Android app. Must the file be part of the project? If I copy the file to phone to folder with other documents my app use and then use that folder, can it work? No need to be compiled with my app?
    – hoacin
    Jun 1, 2017 at 5:14
  • @hoacin You'll need to debug, that's part of programming. If you need code-level assistance, you may email me privately for paid consultation. Google my contact details if you're interested.
    – ABCD
    Jun 2, 2017 at 5:50
1

Finally I made it work with big help of @SmallChess and @Andrew. The first problem came with file stockfish-8-armeabi-v7a with no extension and not much informations about. That's why I asked here. The answer by SmallChess was precise, I just couldn't make things work and I couldn't confirm it for very long time. I run into various problems, more or less easy to deal with, but this one took a lot of time:

I correctly copied the file to folder of my application, but I didn't have permission to run it.

So I had to change it with

string[] cmd = { "chmod", "744", Path.Combine(strToFolder, fileName) };
Java.Lang.Runtime.GetRuntime().Exec(cmd);

and things started to be very easy from now, as Andrew's answer provides fully functional code, which would take also a lot of time to write with not much understanding of the problem, so big thanks to him too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.