Fruit question: pins

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

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

Fruit question: pins

Post by hgm »

I was making a quick hack of Fruit 2.1 to play something other than orthodox Chess, but I stumbled on a piece of code that I don't understand. In move_check.cpp there is a routine find_pins, which says:

Code: Select all

   for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king

      piece = board->square[from];

      delta = king - from;
      ASSERT(delta_is_ok(delta));

      if (PSEUDO_ATTACK(piece,delta)) {

         ASSERT(PIECE_IS_SLIDER(piece));

         inc = DELTA_INC_LINE(delta);
         ASSERT(inc!=IncNone);

         ASSERT(SLIDER_ATTACK(piece,inc));

         sq = from;
         do sq += inc; while ((capture=board->square[sq]) == Empty);

         ASSERT(sq!=king);

         if (COLOUR_IS(capture,me)) {
            pin = sq;
            do sq += inc; while (board->square[sq] == Empty);
            if (sq == king) *list++ = pin;
         }
      }
   }
What I don't understand is how it can guarantee that it only finds sliders. The for-loop runs through the piece list (board->piece[me]), and then it selects on PSEUDO_ATTACK(). The latter is defined in attack.h:

Code: Select all

#define DELTA_INC_LINE(delta)             (DeltaIncLine[DeltaOffset+(delta)])
#define DELTA_INC_ALL(delta)              (DeltaIncAll[DeltaOffset+(delta)])
#define DELTA_MASK(delta)                 (DeltaMask[DeltaOffset+(delta)])

#define INC_MASK(inc)                     (IncMask[IncOffset+(inc)])

#define PIECE_ATTACK(board,piece,from,to) (PSEUDO_ATTACK((piece),(to)-(from))&&line_is_empty((board),(from),(to)))
#define PSEUDO_ATTACK(piece,delta)        (((piece)&DELTA_MASK(delta))!=0)
#define SLIDER_ATTACK(piece,inc)          (((piece)&INC_MASK(inc))!=0)
and measures if the flag set in DeltaMask[] for this delta matches the piece move. But Knight jumps should match too, as the initialization of DeltaMask in attack_init (attack.cpp) also sets the KnightFlag for all Knight delta's:

Code: Select all

   // knight attacks

   for &#40;dir = 0; dir < 8; dir++) &#123;

      delta = KnightInc&#91;dir&#93;;
      ASSERT&#40;delta_is_ok&#40;delta&#41;);

      ASSERT&#40;DeltaIncAll&#91;DeltaOffset+delta&#93;==IncNone&#41;;
      DeltaIncAll&#91;DeltaOffset+delta&#93; = delta;
      DeltaMask&#91;DeltaOffset+delta&#93; |= KnightFlag;
   &#125;
From is_attacked() in the same file it is obvious that the piece list should also contain Knights:

Code: Select all

   // piece attack

   for &#40;ptr = &board->piece&#91;colour&#93;&#91;0&#93;; &#40;from=*ptr&#41; != SquareNone; ptr++) &#123;

      piece = board->square&#91;from&#93;;
      delta = to - from;

      if &#40;PSEUDO_ATTACK&#40;piece,delta&#41;) &#123;

         inc = DELTA_INC_ALL&#40;delta&#41;;
         ASSERT&#40;inc!=IncNone&#41;;

         sq = from;
         do &#123;
            sq += inc;
            if &#40;sq == to&#41; return true;
         &#125; while &#40;board->square&#91;sq&#93; == Empty&#41;;
      &#125;
   &#125;
So how come the is_pinned() routine does not choke on the ASSERT(PIECE_IS_SLIDER(piece)) ???
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Fruit question: pins

Post by Michael Sherwin »

Just a guess: && line_is_empty((board)...
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
User avatar
hgm
Posts: 27814
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Fruit question: pins

Post by hgm »

I don't see how:

Code: Select all

bool line_is_empty&#40;const board_t * board, int from, int to&#41; &#123;

   int delta;
   int inc, sq;

   ASSERT&#40;board!=NULL&#41;;
   ASSERT&#40;SQUARE_IS_OK&#40;from&#41;);
   ASSERT&#40;SQUARE_IS_OK&#40;to&#41;);

   delta = to - from;
   ASSERT&#40;delta_is_ok&#40;delta&#41;);

   inc = DELTA_INC_ALL&#40;delta&#41;;
   ASSERT&#40;inc!=IncNone&#41;;

   sq = from;
   do &#123;
      sq += inc;
      if &#40;sq == to&#41; return true;
   &#125; while &#40;board->square&#91;sq&#93; == Empty&#41;;

   return false; // blocker
&#125;
For a Knight delta the first iteration of the do-loop should find sq==to and return true immediately. Also the code from is_attacked(), which is supposed to also find Knight and King attacks, uses exactly the same PSEUDO_ATTACK() filtering.

I would be inclined to write if(PSEUDO_ATTACK(piece & QueenFlags, delta)), to only consider the Rook and Bishop moves of the piece. This would prevent Knights from causing pseudo-attacks. (And incidentally also would make the code work for Knight + slider compounds.)
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: Fruit question: pins

Post by Karlo Bala »

hgm wrote:I was making a quick hack of Fruit 2.1 to play something other than orthodox Chess, but I stumbled on a piece of code that I don't understand. In move_check.cpp there is a routine find_pins, which says:

Code: Select all

   for &#40;ptr = &board->piece&#91;me&#93;&#91;1&#93;; &#40;from=*ptr&#41; != SquareNone; ptr++) &#123; // HACK&#58; no king

      piece = board->square&#91;from&#93;;

      delta = king - from;
      ASSERT&#40;delta_is_ok&#40;delta&#41;);

      if &#40;PSEUDO_ATTACK&#40;piece,delta&#41;) &#123;

         ASSERT&#40;PIECE_IS_SLIDER&#40;piece&#41;);

         inc = DELTA_INC_LINE&#40;delta&#41;;
         ASSERT&#40;inc!=IncNone&#41;;

         ASSERT&#40;SLIDER_ATTACK&#40;piece,inc&#41;);

         sq = from;
         do sq += inc; while (&#40;capture=board->square&#91;sq&#93;) == Empty&#41;;

         ASSERT&#40;sq!=king&#41;;

         if &#40;COLOUR_IS&#40;capture,me&#41;) &#123;
            pin = sq;
            do sq += inc; while &#40;board->square&#91;sq&#93; == Empty&#41;;
            if &#40;sq == king&#41; *list++ = pin;
         &#125;
      &#125;
   &#125;
What I don't understand is how it can guarantee that it only finds sliders. The for-loop runs through the piece list (board->piece[me]), and then it selects on PSEUDO_ATTACK(). The latter is defined in attack.h:

Code: Select all

#define DELTA_INC_LINE&#40;delta&#41;             &#40;DeltaIncLine&#91;DeltaOffset+&#40;delta&#41;&#93;)
#define DELTA_INC_ALL&#40;delta&#41;              &#40;DeltaIncAll&#91;DeltaOffset+&#40;delta&#41;&#93;)
#define DELTA_MASK&#40;delta&#41;                 &#40;DeltaMask&#91;DeltaOffset+&#40;delta&#41;&#93;)

#define INC_MASK&#40;inc&#41;                     &#40;IncMask&#91;IncOffset+&#40;inc&#41;&#93;)

#define PIECE_ATTACK&#40;board,piece,from,to&#41; &#40;PSEUDO_ATTACK&#40;&#40;piece&#41;,&#40;to&#41;-&#40;from&#41;)&&line_is_empty&#40;&#40;board&#41;,&#40;from&#41;,&#40;to&#41;))
#define PSEUDO_ATTACK&#40;piece,delta&#41;        ((&#40;piece&#41;&DELTA_MASK&#40;delta&#41;)!=0&#41;
#define SLIDER_ATTACK&#40;piece,inc&#41;          ((&#40;piece&#41;&INC_MASK&#40;inc&#41;)!=0&#41;
and measures if the flag set in DeltaMask[] for this delta matches the piece move. But Knight jumps should match too, as the initialization of DeltaMask in attack_init (attack.cpp) also sets the KnightFlag for all Knight delta's:

Code: Select all

   // knight attacks

   for &#40;dir = 0; dir < 8; dir++) &#123;

      delta = KnightInc&#91;dir&#93;;
      ASSERT&#40;delta_is_ok&#40;delta&#41;);

      ASSERT&#40;DeltaIncAll&#91;DeltaOffset+delta&#93;==IncNone&#41;;
      DeltaIncAll&#91;DeltaOffset+delta&#93; = delta;
      DeltaMask&#91;DeltaOffset+delta&#93; |= KnightFlag;
   &#125;
From is_attacked() in the same file it is obvious that the piece list should also contain Knights:

Code: Select all

   // piece attack

   for &#40;ptr = &board->piece&#91;colour&#93;&#91;0&#93;; &#40;from=*ptr&#41; != SquareNone; ptr++) &#123;

      piece = board->square&#91;from&#93;;
      delta = to - from;

      if &#40;PSEUDO_ATTACK&#40;piece,delta&#41;) &#123;

         inc = DELTA_INC_ALL&#40;delta&#41;;
         ASSERT&#40;inc!=IncNone&#41;;

         sq = from;
         do &#123;
            sq += inc;
            if &#40;sq == to&#41; return true;
         &#125; while &#40;board->square&#91;sq&#93; == Empty&#41;;
      &#125;
   &#125;


So how come the is_pinned() routine does not choke on the ASSERT(PIECE_IS_SLIDER(piece)) ???

In DeltaMask[DeltaOffset+(delta)], masks for sliders are 32, 64 or 96. White knight on board is 17, and black knight is 18. So for knights (piece)&DELTA_MASK(delta) are 0.
Am I missing something?
Best Regards,
Karlo Balla Jr.
User avatar
hgm
Posts: 27814
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Fruit question: pins

Post by hgm »

Karlo Bala wrote:In DeltaMask[DeltaOffset+(delta)], masks for sliders are 32, 64 or 96. White knight on board is 17, and black knight is 18. So for knights (piece)&DELTA_MASK(delta) are 0.
Am I missing something?
But the mask for Knights in DeltaMask[DeltaOffset+(delta)] is 16 (KnightFlag), as (part of) the initialization code of DeltaMask below shows:

Code: Select all

   // knight attacks

   for &#40;dir = 0; dir < 8; dir++) &#123;

      delta = KnightInc&#91;dir&#93;;
      ASSERT&#40;delta_is_ok&#40;delta&#41;);

      ASSERT&#40;DeltaIncAll&#91;DeltaOffset+delta&#93;==IncNone&#41;;
      DeltaIncAll&#91;DeltaOffset+delta&#93; = delta;
      DeltaMask&#91;DeltaOffset+delta&#93; |= KnightFlag;
   &#125;
So Knights should give a match, if positioned a Knight's jump away from the King.

I guess that what I am missing is that this is not a general routine to detect pins, but only used on positions where you are not in check.
mar
Posts: 2559
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Fruit question: pins

Post by mar »

hgm wrote:I guess that what I am missing is that this is not a general routine to detect pins, but only used on positions where you are not in check.
From what I understand from the source this is only used in qsearch to generate checks. So I guess find_pins is used to generate discovered checks?

I also don't understand how the code can only iterate sliders. Are you sure the assert doesn't trigger?
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: Fruit question: pins

Post by Karlo Bala »

hgm wrote:
Karlo Bala wrote:In DeltaMask[DeltaOffset+(delta)], masks for sliders are 32, 64 or 96. White knight on board is 17, and black knight is 18. So for knights (piece)&DELTA_MASK(delta) are 0.
Am I missing something?
But the mask for Knights in DeltaMask[DeltaOffset+(delta)] is 16 (KnightFlag), as (part of) the initialization code of DeltaMask below shows:

Code: Select all

   // knight attacks

   for &#40;dir = 0; dir < 8; dir++) &#123;

      delta = KnightInc&#91;dir&#93;;
      ASSERT&#40;delta_is_ok&#40;delta&#41;);

      ASSERT&#40;DeltaIncAll&#91;DeltaOffset+delta&#93;==IncNone&#41;;
      DeltaIncAll&#91;DeltaOffset+delta&#93; = delta;
      DeltaMask&#91;DeltaOffset+delta&#93; |= KnightFlag;
   &#125;
So Knights should give a match, if positioned a Knight's jump away from the King.

I guess that what I am missing is that this is not a general routine to detect pins, but only used on positions where you are not in check.
You are right. Pin detection is used for generating quiet checks, and only when side on move is not in check.
Best Regards,
Karlo Balla Jr.
User avatar
hgm
Posts: 27814
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Fruit question: pins

Post by hgm »

Now this mystery was solved, I made some progress: I have hacked Fruit to play Seirawan Chess! (Also know as S-Chess, hence the name 'S-Fruit'). The capability to use the BN and RN compound already has worked for some time, and I tested it against Fairy-Max win 'Chancellor Chess' and 'Archbishop Chess' (which replace the Queen in the opening position by RN and BN, respectively), and S-Fruit won in both cases 10-0, after I fixed a bug in SEE (which valued the new pieces at 0, making Fairy-Max occasionally win).

But now I have also implemented gating, so that pieces can start in hand. The following is the first S-Chess game it ever played:

Code: Select all

&#91;Event "Computer Chess Game"&#93;
&#91;Site "hgm-xboard"&#93;
&#91;Date "2015.01.14"&#93;
&#91;Round "-"&#93;
&#91;White "S-Fruit 2.1 &#40;UCI2WB&#41;"&#93;
&#91;Black "Fairy-Max 4.8V"&#93;
&#91;Result "1-0"&#93;
&#91;TimeControl "40/60"&#93;
&#91;Variant "seirawan"&#93;
&#91;Annotator "1. +0.16   1... +0.27"&#93;

1. Nc3 &#123;+0.16/10&#125; Nc6/H &#123;+0.27/6 0.9&#125; 2. d4 &#123;+0.68/10 1.8&#125; Nf6/E
&#123;-0.05/6 2.2&#125; 3. d5 &#123;+1.14/9 1.8&#125; Ne5 &#123;-0.15/7 2.0&#125; 4. f4 &#123;+1.40/10 1.9&#125;
Neg4 &#123;-0.22/7 2.4&#125; 5. e4 &#123;+1.72/10 1.5&#125; d6 &#123;-0.21/6 1.4&#125; 6. h3
&#123;+2.38/9 1.6&#125; Nh6 &#123;-0.40/6 1.1&#125; 7. g4 &#123;+2.37/9 1.6&#125; Nhxg4 &#123;-1.08/7 1.2&#125; 8.
hxg4 &#123;+3.18/6 0.5&#125; Bxg4 &#123;-1.36/7 2.3&#125; 9. Nf3/E &#123;+3.33/8 1.5&#125; Hd7
&#123;-1.22/5 1.2&#125; 10. e5 &#123;+3.55/8 1.7&#125; dxe5 &#123;-1.71/8 1.4&#125; 11. fxe5
&#123;+4.45/8 1.1&#125; Bxf3 &#123;-1.84/8 2.2&#125; 12. Exf3 &#123;+4.69/8 1.2&#125; Ng4 &#123;-1.96/7 1.9&#125;
13. Exf7 &#123;+4.75/8 1.7&#125; Nxe5 &#123;-2.27/7 0.8&#125; 14. Exd8+ &#123;+4.95/7 1.4&#125; Rxd8
&#123;-2.36/7 2.4&#125; 15. Bh3 &#123;+5.10/8 1.4&#125; Hb8 &#123;-2.62/7 1.2&#125; 16. Rf1/H
&#123;+6.30/8 1.4&#125; g6 &#123;-2.91/8 1.6&#125; 17. Qe2 &#123;+7.29/9 1.2&#125; c5 &#123;-4.05/7 1.0&#125; 18.
Qb5+ &#123;+9.08/8 1.4&#125; Rd7 &#123;-4.91/7 0.9&#125; 19. Bxd7+ &#123;+11.41/8 1.1&#125; Hxd7
&#123;-6.67/10 3&#125; 20. Qxb7 &#123;+11.58/10 1.3&#125; Hb6 &#123;-7.03/9 3&#125; 21. Qb8+
&#123;+12.22/8 1.0&#125; Hd8 &#123;-7.73/8 2.0&#125; 22. Nb5 &#123;+14.91/9 3&#125; Bh6 &#123;-6.91/6 0.7&#125; 23.
He4 &#123;+1000.09/7 3&#125; Nf3+ &#123;-10.53/7 0.6&#125; 24. Rxf3 &#123;+1000.05/13 0.7&#125; Bf4
&#123;-16.89/7 0.7&#125; 25. Rxf4 &#123;+1000.04/32 0.8&#125; Ef6 &#123;-79.97/9 1.0&#125; 26. Rxf6
&#123;+1000.03/41 1.0&#125; exf6 &#123;-79.98/9 1.2&#125; 27. Hd6+ &#123;+1000.02/34 0.3&#125; Kd7
&#123;-79.99/10 0.7&#125; 28. Qc8# &#123;+1000.01/39 1.1&#125;
&#123;mate&#125; 1-0
There still is some work to do, however:
*) Gating at the Rook square during castling is not implemented yet
*) When I compile Fruit with the DEBUG option, it still triggers an ASSERT: it complains that depth>=0 when in_check in ful_quiescence(). (Because it passes an earlier assert at the top of that routine, this must mean depth=0.)
I will have to study Fruit's search to understand what that means. It could be that this is caused by checking with freshly gated pieces not being classified as checks in an earlier stage. Just ignoring that (by compiling without the DEBUG option) doesn't seem very detrimental, as it decisively crushed Fairy-Max. This is to be expected if the only problem is that it doesn't consider checks with the gated pieces as checks, as these are not supposed to play any tactical role in normal games, and can only happen in silly lines where one side exposes his King in the opening.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Fruit question: pins

Post by Sven »

hgm wrote:Now this mystery was solved, I made some progress: I have hacked Fruit to play Seirawan Chess! (Also know as S-Chess, hence the name 'S-Fruit'). The capability to use the BN and RN compound already has worked for some time, and I tested it against Fairy-Max win 'Chancellor Chess' and 'Archbishop Chess' (which replace the Queen in the opening position by RN and BN, respectively), and S-Fruit won in both cases 10-0, after I fixed a bug in SEE (which valued the new pieces at 0, making Fairy-Max occasionally win).

But now I have also implemented gating, so that pieces can start in hand. The following is the first S-Chess game it ever played:

Code: Select all

&#91;Event "Computer Chess Game"&#93;
&#91;Site "hgm-xboard"&#93;
&#91;Date "2015.01.14"&#93;
&#91;Round "-"&#93;
&#91;White "S-Fruit 2.1 &#40;UCI2WB&#41;"&#93;
&#91;Black "Fairy-Max 4.8V"&#93;
&#91;Result "1-0"&#93;
&#91;TimeControl "40/60"&#93;
&#91;Variant "seirawan"&#93;
&#91;Annotator "1. +0.16   1... +0.27"&#93;

1. Nc3 &#123;+0.16/10&#125; Nc6/H &#123;+0.27/6 0.9&#125; 2. d4 &#123;+0.68/10 1.8&#125; Nf6/E
&#123;-0.05/6 2.2&#125; 3. d5 &#123;+1.14/9 1.8&#125; Ne5 &#123;-0.15/7 2.0&#125; 4. f4 &#123;+1.40/10 1.9&#125;
Neg4 &#123;-0.22/7 2.4&#125; 5. e4 &#123;+1.72/10 1.5&#125; d6 &#123;-0.21/6 1.4&#125; 6. h3
&#123;+2.38/9 1.6&#125; Nh6 &#123;-0.40/6 1.1&#125; 7. g4 &#123;+2.37/9 1.6&#125; Nhxg4 &#123;-1.08/7 1.2&#125; 8.
hxg4 &#123;+3.18/6 0.5&#125; Bxg4 &#123;-1.36/7 2.3&#125; 9. Nf3/E &#123;+3.33/8 1.5&#125; Hd7
&#123;-1.22/5 1.2&#125; 10. e5 &#123;+3.55/8 1.7&#125; dxe5 &#123;-1.71/8 1.4&#125; 11. fxe5
&#123;+4.45/8 1.1&#125; Bxf3 &#123;-1.84/8 2.2&#125; 12. Exf3 &#123;+4.69/8 1.2&#125; Ng4 &#123;-1.96/7 1.9&#125;
13. Exf7 &#123;+4.75/8 1.7&#125; Nxe5 &#123;-2.27/7 0.8&#125; 14. Exd8+ &#123;+4.95/7 1.4&#125; Rxd8
&#123;-2.36/7 2.4&#125; 15. Bh3 &#123;+5.10/8 1.4&#125; Hb8 &#123;-2.62/7 1.2&#125; 16. Rf1/H
&#123;+6.30/8 1.4&#125; g6 &#123;-2.91/8 1.6&#125; 17. Qe2 &#123;+7.29/9 1.2&#125; c5 &#123;-4.05/7 1.0&#125; 18.
Qb5+ &#123;+9.08/8 1.4&#125; Rd7 &#123;-4.91/7 0.9&#125; 19. Bxd7+ &#123;+11.41/8 1.1&#125; Hxd7
&#123;-6.67/10 3&#125; 20. Qxb7 &#123;+11.58/10 1.3&#125; Hb6 &#123;-7.03/9 3&#125; 21. Qb8+
&#123;+12.22/8 1.0&#125; Hd8 &#123;-7.73/8 2.0&#125; 22. Nb5 &#123;+14.91/9 3&#125; Bh6 &#123;-6.91/6 0.7&#125; 23.
He4 &#123;+1000.09/7 3&#125; Nf3+ &#123;-10.53/7 0.6&#125; 24. Rxf3 &#123;+1000.05/13 0.7&#125; Bf4
&#123;-16.89/7 0.7&#125; 25. Rxf4 &#123;+1000.04/32 0.8&#125; Ef6 &#123;-79.97/9 1.0&#125; 26. Rxf6
&#123;+1000.03/41 1.0&#125; exf6 &#123;-79.98/9 1.2&#125; 27. Hd6+ &#123;+1000.02/34 0.3&#125; Kd7
&#123;-79.99/10 0.7&#125; 28. Qc8# &#123;+1000.01/39 1.1&#125;
&#123;mate&#125; 1-0
There still is some work to do, however:
*) Gating at the Rook square during castling is not implemented yet
*) When I compile Fruit with the DEBUG option, it still triggers an ASSERT: it complains that depth>=0 when in_check in ful_quiescence(). (Because it passes an earlier assert at the top of that routine, this must mean depth=0.)
I will have to study Fruit's search to understand what that means. It could be that this is caused by checking with freshly gated pieces not being classified as checks in an earlier stage. Just ignoring that (by compiling without the DEBUG option) doesn't seem very detrimental, as it decisively crushed Fairy-Max. This is to be expected if the only problem is that it doesn't consider checks with the gated pieces as checks, as these are not supposed to play any tactical role in normal games, and can only happen in silly lines where one side exposes his King in the opening.
If a program asserts some particular condition at a given point in the code this often implies that the algorithm relies on this condition being true, so ignoring it is not desired.

In your case I'd say it is possible that full_search() calls full_quiescence() with depth=0 even though the moving side is currently in check, but this was not detected in full_search somehow.
User avatar
hgm
Posts: 27814
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Fruit question: pins

Post by hgm »

True, I am not completely at ease about this. Fruit is extremely generous in ASSERTs, however, and when I started to test my hacked version with DEBUG on, for the first few ASSERTs that triggered I simply could adapt the test in the assert. (E.g. on the total number of pieces; the piece-list are actually large enough to hold 31 non-Pawns for each side, plus 15 Pawns, but the ASSERTs limit it to how many you could acquire by playing from the standard opening position. Which, in case of S-Chess, is of coursetwo more than for regular Chess.)

It doesn't seem to crash because of this failing assert, and actually plays a pretty strong game, beating all other publicly available engines by 10-0. But against stronger opposition it could of course matter.