EPD destruction tests

Discussion of chess software programming and technical issues.

Moderators: bob, hgm, Harvey Williamson

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
User avatar
hgm
Posts: 24449
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: EPD destruction tests

Post by hgm » Mon Feb 24, 2020 10:33 pm

For each captured Pawn you can promote three, after a PxP (a4, a5, a6, axb7 and now the three remaining a- and b-Pawns can promote). Capturing pieces can create only two passers, and in addition defeats the purpose. So maximally 12 Pawns can promote, without any pieces captured.

bob
Posts: 20896
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: EPD destruction tests

Post by bob » Tue Feb 25, 2020 5:23 am

Terje wrote:
Mon Feb 24, 2020 5:07 pm
bob wrote:
Mon Feb 24, 2020 5:00 pm
I coded this in a simple way. Things like wp are just the popcnt(white pawns).

if (wp > 8) {
Print(4095, "illegal position, too many white pawns\n");
error = 1;
}
if (wp + wn > 10) {
Print(4095, "illegal position, too many white knights\n");
error = 1;
}
if (wp + wb > 10) {
Print(4095, "illegal position, too many white bishops\n");
error = 1;
}
if (wp + wr > 10) {
Print(4095, "illegal position, too many white rooks\n");
error = 1;
}
if (wp + wq > 9) {
Print(4095, "illegal position, too many white queens\n");
error = 1;
}
if (wk == 0) {
Print(4095, "illegal position, no white king\n");
error = 1;
}
if (wk > 1) {
Print(4095, "illegal position, multiple white kings\n");
error = 1;
}
if (wp + wn + wb + wr + wq > 15) {
Print(4095, "illegal position, too many white pieces\n");
error = 1;
}

Since that is hardly ever executed I made it simple so that it would be a very small piece of code that can be proven to be bug-free. Repeat for black. I use the "error=1" idea so that I can display ALL the flaws in the position, rather than just exiting after the first. At the bottom, it returns error which is initialized to zero and stays there unless one or more errors are found.

BTW the above will catch all illegal positions. Can't have more than 9 or 10 of each piece type. 8 for pawns. Adding up all pieces and pawns has to be <= 15.
A position with 6wp 4wn 4wb 0wr 0wq 1wk will pass the test, despite having 4 promoted pieces for only 2 missing pawns, no?
I had fixed 99% of that a few years ago. Last week when the FEN question first came up, I caught the total promotions can't be greater than 8 - pawns. However, the code had gotten longer and when I did the copy, I failed to notice there was more below. When we started the FEN discussion, I started making up FENs that would trip up on any of the tests I had, to make sure there were no edge cases that got by. The only one I found that caused an issue was exactly the case you mentioned. Another qualification on the number of pieces of each type. Later today I posted the correct copy/past which shows all the tests. Note that I don't just produce an error. I try to be very specific to tell the user exactly what was wrong. I've been doing this for 30+ years after running into the O/S on our old xerox machine (initially UTS). The command line interpreter was called "tel" and it had a great error reporting approach. For ANY command that was illegal, no matter what the reason, it said "eh?". REALLY informative when trying to debug a shell script. I complained as I knew the O/S guys personally. Their fix, in the next version, was "eh? at 25. Which means it found some sort of an error that apparently started at character 25. That got real old, real quick. It reminded me of our old IBM 1620. You compiled a program, it produced an object deck of cards. You stuck those in the card reader, it would link and load into memory and start executing. If the program failed in any way, a red "check stop" light came on and the machine was now completely dead. You could flip switches to look directly into memory, which was "the debugger" of the 60's. :)

That's why my error checking code is so long, so that it can produce very precise messages explaining what was wrong.

chrisw
Posts: 3112
Joined: Tue Apr 03, 2012 2:28 pm

Re: EPD destruction tests

Post by chrisw » Tue Feb 25, 2020 1:15 pm

hgm wrote:
Mon Feb 24, 2020 10:33 pm
For each captured Pawn you can promote three, after a PxP (a4, a5, a6, axb7 and now the three remaining a- and b-Pawns can promote). Capturing pieces can create only two passers, and in addition defeats the purpose.
in piece capture case, I may be missing why purpose defeated. For a piece capture, the two max passers would appear to be the own pawn that did the capture and an opp pawn which was on same file as own pawn and now has a clear path. Why can’t we usefully apply the fact that max adjust for EITHER side is 1 unit per missing opponent piece ? No doubt I’ve not thought this through enough ...
So maximally 12 Pawns can promote, without any pieces captured.

chrisw
Posts: 3112
Joined: Tue Apr 03, 2012 2:28 pm

Re: EPD destruction tests

Post by chrisw » Tue Feb 25, 2020 2:02 pm

bob wrote:
Tue Feb 25, 2020 5:23 am
Terje wrote:
Mon Feb 24, 2020 5:07 pm
bob wrote:
Mon Feb 24, 2020 5:00 pm
I coded this in a simple way. Things like wp are just the popcnt(white pawns).

if (wp > 8) {
Print(4095, "illegal position, too many white pawns\n");
error = 1;
}
if (wp + wn > 10) {
Print(4095, "illegal position, too many white knights\n");
error = 1;
}
if (wp + wb > 10) {
Print(4095, "illegal position, too many white bishops\n");
error = 1;
}
if (wp + wr > 10) {
Print(4095, "illegal position, too many white rooks\n");
error = 1;
}
if (wp + wq > 9) {
Print(4095, "illegal position, too many white queens\n");
error = 1;
}
if (wk == 0) {
Print(4095, "illegal position, no white king\n");
error = 1;
}
if (wk > 1) {
Print(4095, "illegal position, multiple white kings\n");
error = 1;
}
if (wp + wn + wb + wr + wq > 15) {
Print(4095, "illegal position, too many white pieces\n");
error = 1;
}

Since that is hardly ever executed I made it simple so that it would be a very small piece of code that can be proven to be bug-free. Repeat for black. I use the "error=1" idea so that I can display ALL the flaws in the position, rather than just exiting after the first. At the bottom, it returns error which is initialized to zero and stays there unless one or more errors are found.

BTW the above will catch all illegal positions. Can't have more than 9 or 10 of each piece type. 8 for pawns. Adding up all pieces and pawns has to be <= 15.
A position with 6wp 4wn 4wb 0wr 0wq 1wk will pass the test, despite having 4 promoted pieces for only 2 missing pawns, no?
I had fixed 99% of that a few years ago. Last week when the FEN question first came up, I caught the total promotions can't be greater than 8 - pawns. However, the code had gotten longer and when I did the copy, I failed to notice there was more below. When we started the FEN discussion, I started making up FENs that would trip up on any of the tests I had, to make sure there were no edge cases that got by. The only one I found that caused an issue was exactly the case you mentioned. Another qualification on the number of pieces of each type. Later today I posted the correct copy/past which shows all the tests.
it’s positively a miracle how anything ever mentioned ever always is to be found in a prior Crafty

Note that I don't just produce an error. I try to be very specific to tell the user exactly what was wrong. I've been doing this for 30+ years after running into the O/S on our old xerox machine (initially UTS). The command line interpreter was called "tel" and it had a great error reporting approach. For ANY command that was illegal, no matter what the reason, it said "eh?". REALLY informative when trying to debug a shell script. I complained as I knew the O/S guys personally. Their fix, in the next version, was "eh? at 25. Which means it found some sort of an error that apparently started at character 25. That got real old, real quick. It reminded me of our old IBM 1620. You compiled a program, it produced an object deck of cards. You stuck those in the card reader, it would link and load into memory and start executing. If the program failed in any way, a red "check stop" light came on and the machine was now completely dead. You could flip switches to look directly into memory, which was "the debugger" of the 60's. :)

That's why my error checking code is so long, so that it can produce very precise messages explaining what was wrong.

User avatar
hgm
Posts: 24449
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: EPD destruction tests

Post by hgm » Tue Feb 25, 2020 2:52 pm

chrisw wrote:
Tue Feb 25, 2020 1:15 pm
hgm wrote:
Mon Feb 24, 2020 10:33 pm
For each captured Pawn you can promote three, after a PxP (a4, a5, a6, axb7 and now the three remaining a- and b-Pawns can promote). Capturing pieces can create only two passers, and in addition defeats the purpose.
in piece capture case, I may be missing why purpose defeated. For a piece capture, the two max passers would appear to be the own pawn that did the capture and an opp pawn which was on same file as own pawn and now has a clear path. Why can’t we usefully apply the fact that max adjust for EITHER side is 1 unit per missing opponent piece ? No doubt I’ve not thought this through enough ...
So maximally 12 Pawns can promote, without any pieces captured.
Well, capture of a piece creates two passers, but one of the passers (the opposing one) will be needed to recover that piece. So that side would not get any more pieces than it had. This is what I meant by 'defeats the purpose'. If you do PxP you not only make the capturing Pawn and the opposing one a passer (well, actually just an unblocked Pawn), but also the Pawn opposing the one you captured.

Terje
Posts: 172
Joined: Tue Nov 19, 2019 3:34 am
Location: https://github.com/TerjeKir/weiss
Full name: Terje Kirstihagen

Re: EPD destruction tests

Post by Terje » Tue Feb 25, 2020 4:36 pm

bob wrote:
Mon Feb 24, 2020 5:55 pm
OK, am back. Here is a better cut and paste from a longer terminal window.

Code: Select all

  wp = PopCnt(Pawns(white));
  wn = PopCnt(Knights(white));
  wb = PopCnt(Bishops(white));
  wr = PopCnt(Rooks(white));
  wq = PopCnt(Queens(white));
  wk = PopCnt(Kings(white));

   if (wp > 8) {
    Print(4095, "ERROR-- illegal position, too many white pawns\n");
    error = 1;
  }
  if (wn > 10) {
    Print(4095, "ERROR-- illegal position, too many white knights\n");
    error = 1;
  }
  if (wb > 10) {
    Print(4095, "ERROR-- illegal position, too many white bishops\n");
    error = 1;
  }
  if (wr > 10) {
    Print(4095, "ERROR-- illegal position, too many white rooks\n");
    error = 1;
  }
  if (wq > 9) {
    Print(4095, "ERROR-- illegal position, too many white queens\n");
    error = 1;
  }
  if (wk == 0) {
    Print(4095, "ERROR-- illegal position, no white king\n");
    error = 1;
  }
  if (wk > 1) {
    Print(4095, "ERROR-- illegal position, multiple white kings\n");
    error = 1;
  }
  if (wp + wn + wb + wr + wq > 15) {
    Print(4095, "ERROR-- illegal position, too many white pieces\n");
    error = 1;
  }
  //  remove original pieces from the counts so that wq and such will only count promoted queens, etc.
  wq = Max(wq-1, 0);
  wr = Max(wr-2, 0);
  wb = Max(wb-2, 0);
  wn = Max(wn-2, 0);
  if (wq + wr + wb + wn > 8 - wp) {
    Print(4095, "ERROR-- white has promoted too many pawns\n");
    error = 1;
  }
  if (Pawns(white) & (rank_mask[RANK1] | rank_mask[RANK8])) {
    Print(4095, "ERROR-- illegal position, white pawns on first/eighth rank(s)\n");
    error = 1;
  }
This was modified a few days ago when the FEN parsing thread started. I ran dozens of intentionally broken FEN strings through it and to the best of my knowledge it works. Could have always overlooked a special case, but I tried all the obvious ones in a large batch test.

There is a hole in the above but I don't see any way to correct it without game history. IE if you have two white queens on the board, they COULD be 1 original + 1 promoted; OR, they could be two promoted queens. Can't determine that without information that is not included in FEN. I ignore the possibility myself since there appears to be no way to fix it.
This can still fail if we have 2 wb on same color squares, as it doesn't recognize that one of them must have been promoted (unless I'm missing something).

User avatar
hgm
Posts: 24449
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: EPD destruction tests

Post by hgm » Tue Feb 25, 2020 5:07 pm

9 Bishops on the same color could also be a problem, if not enough opponent pieces have been captured. And it could also depend on where they are. When black still has all his pieces, and Pawns on a7, c7, e7 and g7, having two white Bishops on the same shade on ranks 1-7 would even be impossible if white had no Pawns at all.

bob
Posts: 20896
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: EPD destruction tests

Post by bob » Tue Feb 25, 2020 8:44 pm

chrisw wrote:
Tue Feb 25, 2020 2:02 pm
it’s positively a miracle how anything ever mentioned ever always is to be found in a prior Crafty
You can look at older versions of Crafty if you don't believe it. There are dozens of versions hanging around.

Here's the comments from main.c that ANYBODY can verify. ValidPosition() was added in version 19.20. Comments:

Code: Select all

 *   19.20   Bug in the EvaluateMaterial() (bad trade) code that would not     *
 *           penalize a single piece vs 3 pawns properly.  Now the penalty is  *
 *           added in unless the side with the piece has nothing else to go    *
 *           with it at all (no pawns or other pieces).  Pawn scoring changed, *
 *           doubled pawns were scored too badly because the penalties were    *
 *           added twice (as expected) but they were set as if they were just  *
 *           added once.  Eval command also had a bug in displaying the pawn   *
 *           evaluation parameters.  Move input changed to accept pawn         *
 *           promotions of the form a8Q (this is needed as ChessBase violates  *
 *           the PGN/SAN standard that mandates a8=Q as the proper syntax for  *
 *           pawn promotions.)  annoying glitch in epdglue.c that would        *
 *           produce the wrong score for positions with exactly one legal move *
 *           was fixed.  <b>New InvalidPosition() function verifies that FEN      *
 *           setup positions are reasonable, without extra pawns or too many   *
 *           pieces total, etc.</b>  Passed pawn to 7th search extension removed,  *
 *           mate threat extension tuned down to 1/2 ply.  Bug in SetBoard()   *
 *           fixed.  This bug made it impossible to import many epd records    *
 *           due to incorrectly handling the wtm flag.  This was introduced in *
 *           the recent changes to disallow certain types of illegal positions *
 *           that were impossible (more than 9 queens of one color, etc.) new  *
 *           eval term for space added.  
Here's the code from that version (again, anybody can verify where it came from):

Code: Select all

/* last modified 06/13/05 */
/*
 *******************************************************************************
 *                                                                             *
 *   InvalidPosition() is used to determine if the position just entered via a *
 *   FEN-string or the "edit" command is legal.  This includes the expected    *
 *   tests for too many pawns or pieces for one side, pawns on impossible      *
 *   squares, and the like.                                                    *
 *                                                                             *
 *******************************************************************************
 */
int InvalidPosition(TREE * RESTRICT tree)
{
  int error = 0;
  int wp, wn, wb, wr, wq, bp, bn, bb, br, bq;
  wp = PopCnt(WhitePawns);
  wn = PopCnt(WhiteKnights);
  wb = PopCnt(WhiteBishops);
  wr = PopCnt(WhiteRooks);
  wq = PopCnt(WhiteQueens);
  bp = PopCnt(BlackPawns);
  bn = PopCnt(BlackKnights);
  bb = PopCnt(BlackBishops);
  br = PopCnt(BlackRooks);
  bq = PopCnt(BlackQueens);
  if (wp > 8) {
    Print(4095, "illegal position, too many white pawns\n");
    error = 1;
  }
  if (wp + wn > 10) {
    Print(4095, "illegal position, too many white knights\n");
    Print(4095, "illegal position, too many white knights\n");
    error = 1;
  }
  if (wp + wb > 10) {
    Print(4095, "illegal position, too many white bishops\n");
    error = 1;
  }
  if (wp + wr > 10) {
    Print(4095, "illegal position, too many white rooks\n");
    error = 1;
  }
  if (wp + wq > 9) {
    Print(4095, "illegal position, too many white queens\n");
    error = 1;
  }
  if (wp + wn + wb + wr + wq > 15) {
    Print(4095, "illegal position, too many white pieces\n");
    error = 1;
  }
  if (WhitePawns & (rank_mask[RANK1] | rank_mask[RANK8])) {
    Print(4095, "illegal position, white pawns on first/eighth rank(s)\n");
    error = 1;
  }
  if (bp > 8) {
    Print(4095, "illegal position, too many black pawns\n");
    error = 1;
  }
  if (bp + bn > 10) {
    Print(4095, "illegal position, too many black knights\n");
    error = 1;
  }
  if (bp + bb > 10) {
    Print(4095, "illegal position, too many black bishops\n");
    error = 1;
  }
  if (bp + br > 10) {
    Print(4095, "illegal position, too many black rooks\n");
    error = 1;
  }
  if (bp + bq > 9) {
    Print(4095, "illegal position, too many black queens\n");
    error = 1;
  }
  if (bp + bn + bb + br + bq > 15) {
    Print(4095, "illegal position, too many black pieces\n");
    error = 1;
  }
  if (BlackPawns & (rank_mask[RANK1] | rank_mask[RANK8])) {
    Print(4095, "illegal position, black pawns on first/eighth rank(s)\n");
    error = 1;
  }
  if (Check(!wtm)) {
    Print(4095, "ERROR side not on move is in check!\n");
    error = 1;
  }
  return (error);
As you can see, the only hole I left (which I pointed out I fixed when this FEN discussion started) was the total promotions + total pawns <= 8.

Now, why the comment? Does it deflate your ego that someone thought of an idea WAY before you? If you notice above, the comments define when this was originally added: June 13, 2005. Whoop-de-do. If that upsets you, just continue to be upset. Crafty has only been around for 25 years, I'd expect it to be fairly "complete" in such things. But feel free to verify the above first.

JohnWoe
Posts: 183
Joined: Sat Mar 02, 2013 10:31 pm

Re: EPD destruction tests

Post by JohnWoe » Tue Feb 25, 2020 10:19 pm

I only check for en passant validity and there's only 1 king per side. The rest I don't care. Well I also check that castling rooks are where they should be. Very small checks. Other than that my program accepts anything.

bob
Posts: 20896
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: EPD destruction tests

Post by bob » Wed Feb 26, 2020 2:44 am

Used to do it pretty cheaply myself. Somewhere in 2005 I was getting complaints from (I think) a couple of the SSDF folks. I wrote the code that has been used until this thread started. I had gotten everything except for the promotes + pawns <= 8. Funny thing was, when I modified this code, I got far MORE complaints. Because people were using some broken positions to detect Crafty clones. :) However, once written, I did not undo the fixes...

Want to know how long this stuff has been around? Ed Kozdrowicki sent me a text description of what was simply called "Forsythe notation." I think around 1971 after we talked during the infamous 1970 computer chess tournament (first held). I thought it was an elegant solution to a common problem, and have been using it ever since. Steven Edwards then took it and formalized it at some point and it was called FEN from that point on.

It was certainly a step forward, as was PGN. Although both have had their warts to deal with. PGN probably the worst as every tom, dick and harry wrote code to produce PGN that was non-standard in so many ways. Took a lot of work to make a chess program accept all the different PGN collections scattered around the internet. ChessBase being one of the biggest examples.

Post Reply