FEN and 3rd repetition rule. No information?

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
Luis Babboni
Posts: 464
Joined: Sat Feb 28, 2015 4:37 pm
Location: Argentina

FEN and 3rd repetition rule. No information?

Post by Luis Babboni »

Hi people!

With my "stay at home" cause coronavirus, I´m starting a new code for Soberango. When I did the moves generator for my first version of Soberango, I did not planed it to be able to detect 3rd repetition rule so it seems I did not thought in this before.
As far as I understand, the FEN notation do not have information about previous positions.
So, the numbers that you need to found testing moves generators, do not involve 3rd repetition rule.
I´m right?

Thanks!
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: FEN and 3rd repetition rule. No information?

Post by hgm »

In perft a branch is not supposed to stop after a 3-fold repetition. Not sure how it is for an insufficent-material draw, like KNK.

BTW, it is my experience that you cannot really test an engine for strength when it doesn't recognizes repetitions at least at game level. Because almost all games where it is winning will sooner or later end in a repetition.
User avatar
Luis Babboni
Posts: 464
Joined: Sat Feb 28, 2015 4:37 pm
Location: Argentina

Re: FEN and 3rd repetition rule. No information?

Post by Luis Babboni »

Thanks H.G.!

OK!

Yes, yes, after few versions, Soberengo was able to recognize 3rd repetition rule. But not when I did the moves generator that is in the position I´m now with this new version.
chrisw
Posts: 4313
Joined: Tue Apr 03, 2012 4:28 pm

Re: FEN and 3rd repetition rule. No information?

Post by chrisw »

Luis Babboni wrote: Fri Apr 03, 2020 6:05 pm Hi people!

With my "stay at home" cause coronavirus, I´m starting a new code for Soberango. When I did the moves generator for my first version of Soberango, I did not planed it to be able to detect 3rd repetition rule so it seems I did not thought in this before.
As far as I understand, the FEN notation do not have information about previous positions.
So, the numbers that you need to found testing moves generators, do not involve 3rd repetition rule.
I´m right?

Thanks!
There is actually a de facto standard to cover this, which is the position command in UCI protocol.

You can do: position, where position is a FEN string, but also

FEN string moves Bb2 Kf8 ...... and the end position is set together with move history, or basically whatever the engine programmer wants to do with the move history.
User avatar
Luis Babboni
Posts: 464
Joined: Sat Feb 28, 2015 4:37 pm
Location: Argentina

Re: FEN and 3rd repetition rule. No information?

Post by Luis Babboni »

Thanks Chrisw!

I think I´ll use xboard protocol but sounds very nice that.
My concern is that when I´ll use perft results this will be take in account.
It seems not.... at least not for the moment.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: FEN and 3rd repetition rule. No information?

Post by bob »

chrisw wrote: Fri Apr 03, 2020 9:41 pm
Luis Babboni wrote: Fri Apr 03, 2020 6:05 pm Hi people!

With my "stay at home" cause coronavirus, I´m starting a new code for Soberango. When I did the moves generator for my first version of Soberango, I did not planed it to be able to detect 3rd repetition rule so it seems I did not thought in this before.
As far as I understand, the FEN notation do not have information about previous positions.
So, the numbers that you need to found testing moves generators, do not involve 3rd repetition rule.
I´m right?

Thanks!
There is actually a de facto standard to cover this, which is the position command in UCI protocol.

You can do: position, where position is a FEN string, but also

FEN string moves Bb2 Kf8 ...... and the end position is set together with move history, or basically whatever the engine programmer wants to do with the move history.
Where do you see this in the FEN spec??? Or are you talking about non-standard FEN?

When I care about repetition testing, I just suck in a PGN game file and then reset to the move # where the repetition is an interesting issue.

IE in Crafty:

read game.pgn
white|black (to set color)
reset 45 (reset to move 45 with "color" on move
go

Assuming move 45 in the game is where the repetition becomes an issue...

This was an issue I addressed with Tim Mann (original xboard author.) Originally, xboard used a clumsy "edit" command, then it added FEN so that an interrupted game could be continued later. But those damned pesky humans discovered that if they were losing, they could disconnect and then log back in and continue, and Crafty had lost the game history and would frequently fall into a draw. So we added the ability to "stuff" the complete game moves into the engine rather than using FEN/edit. Solved all problems. It was done using the "force" command, which was also a kludge. But it did work to address the problem at hand...
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: FEN and 3rd repetition rule. No information?

Post by hgm »

To know the game history you need to load a partial game. Standard to record games is PGN...
chrisw
Posts: 4313
Joined: Tue Apr 03, 2012 4:28 pm

Re: FEN and 3rd repetition rule. No information?

Post by chrisw »

Luis Babboni wrote: Sat Apr 04, 2020 2:41 am Thanks Chrisw!

I think I´ll use xboard protocol but sounds very nice that.
My concern is that when I´ll use perft results this will be take in account.
It seems not.... at least not for the moment.
I would not use Xboard, UCI is so much better and the documentation way more concise, most 'sensible' people use it, and it's the standard for GUIs and Python Chess. Some old engines still use XBoard and getting some of them to work with Python-Chess for example is a nightmare. I haven't found one UCI chess engine that doesn't run straight out of the box from Python-Chess UI code. UCI documentation download from

https://www.shredderchess.com/chess-inf ... rface.html

Relevant bits of documentation:

position [fen <fenstring> | startpos ] moves <move1> .... <movei>
set up the position described in fenstring on the internal board and
play the moves on the internal chess board.
if the game was played from the start position the string "startpos" will be sent
Note: no "new" command is needed. However, if this position is from a different game than
the last position sent to the engine, the GUI should have sent a "ucinewgame" inbetween.

Move format:
----------------
The move format is in long algebraic notation.
A nullmove from the Engine to the GUI should be sent as 0000.
Examples: e2e4, e7e5, e1g1 (white short castling), e7e8q (for promotion)

So, for example, in a game the position information string would be (assuming startpos, but could be any FEN)
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 moves e2e4
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 moves e2e4 g8f6
etc etc.

That way, your engine doesn't have to keep track of a game history, all that can be handled in the GUI, the engine acting as a "FEN + moves" solver for each position. Externally to the engine, either use a standard GUI, or write your own simple "game player" with Python-Chess, all very straightforward, tried and tested.

All engines that use UCI format will already be parsing these position strings as standard, btw. As engine programmer, you need do no more than ReadFEN(), leave the FEN pointer looking at the end of FEN string, and if you find " moves ", then parse the moves one by one, adjusting your game board, side to move, history, move number and 50 moverule counter accordingly.
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: FEN and 3rd repetition rule. No information?

Post by hgm »

I wouldn't use UCI. It is an inherently defective protocol, that doesn't even allow engines to offer or accept a draw, or to resign.

That some old engines do not properly implement XBoard protocol is not relevant, as long as your own engine has a correct implementation. That equally holds for UCI, btw; avery UCI engine in the world might run smoothly, but if you bungle your own UCI implementation, your engine won't.
chrisw
Posts: 4313
Joined: Tue Apr 03, 2012 4:28 pm

Re: FEN and 3rd repetition rule. No information?

Post by chrisw »

hgm wrote: Sat Apr 04, 2020 1:11 pm I wouldn't use UCI. It is an inherently defective protocol, that doesn't even allow engines to offer or accept a draw, or to resign.

That some old engines do not properly implement XBoard protocol is not relevant, as long as your own engine has a correct implementation. That equally holds for UCI, btw; avery UCI engine in the world might run smoothly, but if you bungle your own UCI implementation, your engine won't.
When I read this kind of stuff in the Xboard documentation, and compare it to the short and concise UCI documentation, and have to choose which one to use, also in knowledge of the system the majority of engines do use, UCI is a no-brainer choice.

Jesus, just look at this below. Problems? Fix problems? Political sideswipes at some other operating systems? No thank you very much. I want to write chess engine, with a UI protocol straightforward, known to work, what everybody uses and where I don't need to trawl through a megabyte of documentation woffle to know what is going on.
Compare the short and non-problematical UCI. Simple. UCI written by commercial programmer, no nonsense, does the job, you don't need to be an expert in weird and wonderful systems to get it to work, quickly. XBoard, written and 'maintained' in academia, and it really shows. I would argue actually, its practically impossible to work with and get functional in any reasonable space of time. There's just too much special in-group language to wade through. Programmers did once, they had no choice, but now there is a choice, they choose UCI, on the whole.



Another way to fix the problem is to use unbuffered operating system calls to write directly to the file descriptor for standard output. On Unix, this means write(1, ...) -- see the man page for write(2). On Win32, you can use either the Unix-like _write(1, ...) or Win32 native routines like WriteFile.

Second, on the input side, you are likely to want to poll during your search and stop it if new input has come in. If you implement pondering, you'll need this so that pondering stops when the user makes a move. You should also poll during normal thinking on your move, so that you can implement the "?" (move now) command, and so that you can respond promptly to a "result", "force", or "quit" command if xboard wants to end the game or terminate your engine. Buffered input makes polling more complicated -- when you poll, you must stop your search if there are either characters in the buffer or characters available from the underlying file descriptor.

The most direct way to fix this problem is to use unbuffered operating system calls to read (and poll) the underlying file descriptor directly. On Unix, use read(0, ...) to read from standard input, and use select() to poll it. See the man pages read(2) and select(2). (Don't follow the example of GNU Chess 4 and use the FIONREAD ioctl to poll for input. It is not very portable; that is, it does not exist on all versions of Unix, and is broken on some that do have it.) On Win32, you can use either the Unix-like _read(0, ...) or the native Win32 ReadFile() to read. Unfortunately, under Win32, the function to use for polling is different depending on whether the input device is a pipe, a console, or something else. (More Microsoft brain damage here -- did they never hear of device independence?) For pipes, you can use PeekNamedPipe to poll (even when the pipe is unnamed). For consoles, you can use GetNumberOfConsoleInputEvents. For sockets only, you can use select(). It might be possible to use WaitForSingleObject more generally, but I have not tried it. Some code to do these things can be found in Crafty's utility.c, but I don't guarantee that it's all correct or optimal.

A second way to fix the problem might be to ask your I/O library not to buffer on input. It should then be safe to poll the underlying file descriptor as described above. With C, you can try calling setbuf(stdin, NULL). However, I have never tried this. Also, there could be problems if you use scanf(), at least with certain patterns, because scanf() sometimes needs to read one extra character and "push it back" into the buffer; hence, there is a one-character pushback buffer even if you asked for stdio to be unbuffered. With C++, you can try cin.rdbuf()->setbuf(NULL, 0), but again, I have never tried this.

A third way to fix the problem is to check whether there are characters in the buffer whenever you poll. C I/O libraries generally do not provide any portable way to do this. Under C++, you can use cin.rdbuf()->in_avail(). This method has been reported to work with EXchess. Remember that if there are no characters in the buffer, you still have to poll the underlying file descriptor too, using the method described above.

A fourth way to fix the problem is to use a separate thread to read from stdin. This way works well if you are familiar with thread programming. This thread can be blocked waiting for input to come in at all times, while the main thread of your engine does its thinking. When input arrives, you have the thread put the input into a buffer and set a flag in a global variable. Your search routine then periodically tests the global variable to see if there is input to process, and stops if there is. WinBoard and my Win32 ports of ICC timestamp and FICS timeseal use threads to handle multiple input sources.