Interfacing with a GUI

Code, algorithms, languages, construction...
ppyvabw
Posts: 29
Joined: Sat Nov 01, 2014 12:51 am
Real Name: Adam

Interfacing with a GUI

Post by ppyvabw » Tue Dec 08, 2015 8:13 pm

I am now trying to interface my engine with a GUI, which is something I have never tried before. I'll probably use Knights (because I like it) and XBoard protocol, but the intention is that ultimately I'd like to be able to play it online automatically to test it -- I don't have time to sit and play hundreds of games to see how well it plays, as much as I'd like to :lol:

From what I have researched so far, is it really just a case of adapting my engine to input and output data in the correct format, and having knights run the engine from a command such as ./directory_to_my_executable/executable? Presumably knights will set up the pipes and do everything else?

Is there a minimum amount of stuff I have to have implemented? At the moment, the only input and output is reading and outputting moves and displaying the PV, score etc... to and from a terminal window -- no clock yet. Is the clock dealt with by the GUI, which passes the time to the engine, or does the engine needs its own clock?

Any advice anyone can give me, or directions to more literature would be really appreciated.

hyatt
Posts: 1242
Joined: Thu Jun 10, 2010 2:13 am
Real Name: Bob Hyatt (Robert M. Hyatt)
Location: University of Alabama at Birmingham
Contact:

Re: Interfacing with a GUI

Post by hyatt » Tue Dec 08, 2015 10:51 pm

ppyvabw wrote:I am now trying to interface my engine with a GUI, which is something I have never tried before. I'll probably use Knights (because I like it) and XBoard protocol, but the intention is that ultimately I'd like to be able to play it online automatically to test it -- I don't have time to sit and play hundreds of games to see how well it plays, as much as I'd like to :lol:

From what I have researched so far, is it really just a case of adapting my engine to input and output data in the correct format, and having knights run the engine from a command such as ./directory_to_my_executable/executable? Presumably knights will set up the pipes and do everything else?

Is there a minimum amount of stuff I have to have implemented? At the moment, the only input and output is reading and outputting moves and displaying the PV, score etc... to and from a terminal window -- no clock yet. Is the clock dealt with by the GUI, which passes the time to the engine, or does the engine needs its own clock?

Any advice anyone can give me, or directions to more literature would be really appreciated.

Key #1. Unbuffered input. IE use read()/write() or if you insist, use buffered I/O but set the buffer size to zero. I use read/write myself.

time/otim are the two time commands, and yes, the GUI manages this and just tells you how many 1/100ths of a second you (time) and opponent (time) have left on the clock. You can almost get away with just those, plus the ability to input and output moves, to be able to play a game. To play more than one you need either "new" or "quit" (and tell the interface to restart program after each game if you only recognize "quit"). If you want to resume games, you can add seaboard (FEN input), or better, the force command so that the GUI can send you all the moves in the game so far, so that when you re-start you will have correct repetition information and such. From there, add what you want and test each before going on to the next...

I found the unbuffered I/O the most painful. But you have to use that if you want to be able to use something like select() to see if there is data buffered and ready for reading.

thevinenator
Posts: 68
Joined: Tue Jun 02, 2015 11:02 pm
Real Name: Vince

Re: Interfacing with a GUI

Post by thevinenator » Wed Dec 09, 2015 4:50 am

the CPW code has one example of how to interface with a GUI. also, look for a series of videos on youtube called "programming a chess engine in C". the author of that goes though the details of how he implemented his I/O code which is different. you can also look at the code available from all the engines out there.

i implemented the ideas in the CPW code for my time control and so far it is working fine. I handled the communication my own way, making use of an extra thread to keep the I/O and search engine separate. this makes it a lot easier to debug since the handshaking between the I/O and search code is simplified (no need for callbacks or other complicated I/O tricks).

The I/O thread (main code thread) has three loops. a "console" loop, one for UCI and another for XBoard. if another interface comes along, it will be easy to add yet another code loop. The philosophy is simple. the program starts out in a console loop, looking for commands from standard input. this could be manually typed commands by a human or, when connected to a GUI, the commands the GUI sends. I have a lot of console commands, which i use for debugging, testing ideas, .etc. if a UCI or xboard command arrives, the console code passes control to the protocol code loop where it stays until a quit occurs. when that happens, the program always exits, it never goes back to console mode.

as i mentioned, I set the code structure in my engine using a separate thread for searching (currently only one search thread). this simplifies the checking that the "thinking" part of your engine needs to do. the threads communicate via a global structure with flags that control everything implemented as a very simple state machine. The I/O code is the master, the search code is the slave. The search code starts and stops as directed and only has to check a couple of flags every so often to find out if it should quit searching.

each developer has their own style and unless they lifted the code directly from another engine, a lot of thought and testing has gone into insuring the communications work correctly. i'm sure you'll appreciate the effort once you complete yours.

putting together a good i/o interface will take a lot of time and testing, but it is very rewarding to see your engine finally playing under the control of a GUI.

good luck
"An Engine's strength flows from the Search. But beware, pruning, extensions, reductions; the dark side of the Search are they. Once you start down the dark path, it will dominate and consume you, as it has to so many developers before.” -- Yoda

H.G.Muller
Posts: 190
Joined: Sun Jul 14, 2013 10:00 am
Real Name: H.G. Muller

Re: Interfacing with a GUI

Post by H.G.Muller » Wed Dec 09, 2015 2:01 pm

ppyvabw wrote:From what I have researched so far, is it really just a case of adapting my engine to input and output data in the correct format, and having knights run the engine from a command such as ./directory_to_my_executable/executable? Presumably knights will set up the pipes and do everything else?
Indeed, it is really that easy. You can find a sample driver for WB protocol on WinBoard forum.

To take care of the buffering problem, I usually just add a fflush(stdout); before the point where you start to read input. Then you can use the normal printf() and getchar() for output and input. Implementing pondering is the most difficult part, because the engine would have to monitor input during the search.

ppyvabw
Posts: 29
Joined: Sat Nov 01, 2014 12:51 am
Real Name: Adam

Re: Interfacing with a GUI

Post by ppyvabw » Fri Dec 11, 2015 1:04 am

Great, thanks for the help!

To be honest, for now I'm not overly worried about a really slick GUI interface with all the bells and whistles, although it would be kind of cool. For the moment, I'm happy playing from the terminal output with a board in front of me. Although I don't think I'm the best metric against which to test it, because I'm only averagely competent at chess, and my inclination is to deliberately play bad moves to see if it spots them. So I just want to be able to play it online, and perhaps for other people to play, just to test it against unbiased opponents to see how well it's playing to tune my evaluation function and find bugs and stuff.

I had the -- probably stupid -- idea of trying to cobble together some bash or python script to run my program against another engine to test/tune it. Just set it going overnight or whilst at work, but decided it would be better to spend weeks/months tackling an actual proper interface rather than spending the same amount of time perfecting a hack, if that makes sense.

thevinenator
Posts: 68
Joined: Tue Jun 02, 2015 11:02 pm
Real Name: Vince

Re: Interfacing with a GUI

Post by thevinenator » Fri Dec 11, 2015 3:54 am

for the longest time i tested my code by using simple commands from the console. i finally bit the bullet and implemented the UCI interface (no politics involved, here). that was a real time saver. i can now run test games or tournaments without having to babysit the engine.

spend the time, interface!

if someone asked me now how to start writing a chess engine, i would tell them, do the interface first.
"An Engine's strength flows from the Search. But beware, pruning, extensions, reductions; the dark side of the Search are they. Once you start down the dark path, it will dominate and consume you, as it has to so many developers before.” -- Yoda

H.G.Muller
Posts: 190
Joined: Sun Jul 14, 2013 10:00 am
Real Name: H.G. Muller

Re: Interfacing with a GUI

Post by H.G.Muller » Fri Dec 11, 2015 6:12 pm

It should only take an hour or so to convert a colsole Chess program to a WinBoard-compatible engine.

ppyvabw
Posts: 29
Joined: Sat Nov 01, 2014 12:51 am
Real Name: Adam

Re: Interfacing with a GUI

Post by ppyvabw » Mon Jan 04, 2016 1:16 am

Hi again,

I'm struggling with this a bit.

I don't think the implementation of my engine in C++ as it stands lends itself very well to making it compatible with a GUI. I think I understand the principle of it now, superficially at least, having studied the CPW code. I'll try to describe my program as well as possible without posting pages and pages of code :lol:

My code uses a 'Player' base class with a virtual method

Code: Select all

bool play(Move& M)
, and polymorphic derived classes 'Human' and 'Eva'. Calling

Code: Select all

bool end=Eva.play(M)
invokes the search function which returns true if there is no legal move, and returns false if there is a legal move. (The move is passed back be reference.) Calling

Code: Select all

bool end=Human.play(M)
calls code that waits for input of a move (at present from the terminal), checks if it is legal and returns it via M (by reference). Again, it returns true if there is no legal move, thus breaking the loop and printing a "end of game".

So my game loop code is essentially just a one-line loop

Code: Select all

  

  player* Player[2];  
  Player[0]=new Human(white,pos);
  Player[1]=new Eva(black,pos);  

  side stm=white;

  for (Move M;Player[stm]->play(M)==false; stm=side(1-stm),M=Move()){
    pos.makemove(M);   
   // (player::Interface)->DisplayBoard(pos);   
  }
  printf("End of Game");

  //delete stuff

In the above, Move() is just a null move, and pos is an instance of a position class that stores all the position data and bitboards and stuff, with methods to make and unmake moves etc...I think the rest should be obvious.

My first thoughts about how to implement an interface with a gui (whilst maintaining the option to run from the terminal too) was create a polymorphic interface class with derived classes for terminal, xboard and uci, with a static pointer to it in the player class. Then I can pass instructions to the interface with something like

Code: Select all

 Interface->Do something
, and similarly for input. I reconfigured my terminal interface to work like this (hence the commented out instruction in the above code)

Subsequent to that I realized that if I wanted to, for example, make my engine play black by sending an instruction from the terminal or from xboard, I'd have to make it leave Human.play(M) where it received the instruction, to switch Player[0] and Player[1] and switch Human and Eva's colours. Perhaps not terribly difficult in itself, but then considering other commands like forcing the engine to move or giving hints, it would probably get more complicated. Also, implementing pondering: I'd have to call the pondering routine from within the Human class (whilst polling for input from the Human), which kind of goes against the object orientated paradigm in my opinion -- pondering would be best called from the Eva class, since it is Eva that is doing the pondering. All that considered, I think it will all quickly become spaghettified. That all probably sounds quite confused, but I hope it made some sense.

I'm not sure that I have a specific question, but any further comments or advice would be helpful. I'm really grateful for all the help thus far :) I'm starting to think I may have hung myself by trying to adhere to OOP principles. (I'm sure it's obvious by now that I am not a professional programmer :oops: )

H.G.Muller
Posts: 190
Joined: Sun Jul 14, 2013 10:00 am
Real Name: H.G. Muller

Re: Interfacing with a GUI

Post by H.G.Muller » Mon Jan 04, 2016 1:39 pm

It seems to me you are thinking the wrong way around here. It is not the engine that should pass instructions to the interface, but the interface that should control the engine. IOW, the engine is a 'server', and the interface is a 'client'.

Although I don't understand C++ the logic of your program seems well suited for conversion to an XBoard engine. But you should get rid of that main loop, and replace it by the protocol driver. So that the engine doesn't do its own thing, but does what the GUI tells it to do. So each time a GUI command implies you would have to make a move (and in XBoard protocol this can be because your turn came up, or because the interface tells you you now have to play for the side whose turn it already was), you would call the routine play(), and print the resulting move in the compliant format when that routine finishes.

You might have to abandon the routine human(), though, as I assume that would only accept moves, while in the standard protocol, in the opponents turn, you could also get all kind of other commands. (E.g. to make you continue the game for the other side, switch pondering off...) So your main loop would look more like

Code: Select all

while(1) {
  if(sideToMove == sideEnginePlays) {
    ThinkUpMove();
    MakeMove(move); // changes sideToMove
    Print(move);
  }
  fflush(stdout); // make sure everything is printed before waiting for input
  command = ReadCommandFromInput();
  if(command == "quit") break;
  if(IsMove(command)) MakeMove(inputMove); else
  if(command == "force") sideEnginePlays = NONE; else
  if(command == "go") sideEnginePlays = sideToMove; else
  if(command == "new") { InitGame(); sideToMove = WHITE; sideEnginePlays = BLACK; } else
  ...
}
I wrote an example driver for a quite complete implementation of the XBoard protocol in my draft for a new specification of the protocol, see http://hgm.nubati.net/CECP.html .

ppyvabw
Posts: 29
Joined: Sat Nov 01, 2014 12:51 am
Real Name: Adam

Re: Interfacing with a GUI

Post by ppyvabw » Tue Jan 05, 2016 1:44 am

Hi,

Thanks for your reply. It looks like you understood my confusion, so thank you.

Yes, I understand that the interface should be the thing that controls the engine, rather than the other way around. But the engine still has to send stuff to the gui, hence my Interface->Do something pseudo code. Equally, at the moment I have lines that do stuff like var=Interface -> get input. My hope is that by writing an interface class that works in terminal (with similar functionality) to get the design features right, then writing a polymorphic interface class for xboard should be (relatively) straightforward.

This afternoon, I did manage to dream up a way of being able to return commands from my Human.play() routine back to that loop, and now that loop controls what the engine is doing, and it does look similar to your example code. I shall persevere, unless I hit another stumbling block, thin I might have to have a rethink. Now that you have said it, abandoning the Human class altogether and replacing that and the loop with an over-riding protocol driver does make more sense.

Thanks for the link; I shall have a look at that, although I am trying not to look too much at other people's code so that I don't inadvertently plagiarize it.

I didn't expect that writing the interface would be almost as difficult as writing the engine :lol:

Thanks again,

Adam

Post Reply