Page 1 of 1

Bad/good bishops in R3 and IPPOLIT/IvanHoe

Posted: Tue Nov 30, 2010 1:29 am
by BB+
First the tables used in pawneval:

Code: Select all

static const uint64 RybkaBlockedPawnValue[64]= /* memloc 0x589110 in gdb */
{0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
0x0001000100000000,0x0000000000020002,0x0003000300000000,0x0000000000040004,0x0004000400000000,0x0000000000030003,0x0002000200000000,0x0000000000010001,
0x0000000000010001,0x0002000200000000,0x0000000000030003,0x0004000400000000,0x0000000000040004,0x0003000300000000,0x0000000000020002,0x0001000100000000,
0x0001000100000000,0x0000000000020002,0x0003000300000000,0x0000000000040004,0x0004000400000000,0x0000000000030003,0x0002000200000000,0x0000000000010001,
0x0000000000010001,0x0002000200000000,0x0000000000030003,0x0004000400000000,0x0000000000040004,0x0003000300000000,0x0000000000020002,0x0001000100000000,
0x0001000100000000,0x0000000000020002,0x0003000300000000,0x0000000000040004,0x0004000400000000,0x0000000000030003,0x0002000200000000,0x0000000000010001,
0x0000000000010001,0x0002000200000000,0x0000000000030003,0x0004000400000000,0x0000000000040004,0x0003000300000000,0x0000000000020002,0x0001000100000000,
0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000}
static const uint64 RybkaBlockedPawnValue_x2[64]= /* memloc 0x589510 in gdb */
{0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
0x0002000200000000,0x0000000000040004,0x0006000600000000,0x0000000000080008,0x0008000800000000,0x0000000000060006,0x0004000400000000,0x0000000000020002,
0x0000000000020002,0x0004000400000000,0x0000000000060006,0x0008000800000000,0x0000000000080008,0x0006000600000000,0x0000000000040004,0x0002000200000000,
0x0002000200000000,0x0000000000040004,0x0006000600000000,0x0000000000080008,0x0008000800000000,0x0000000000060006,0x0004000400000000,0x0000000000020002,
0x0000000000020002,0x0004000400000000,0x0000000000060006,0x0008000800000000,0x0000000000080008,0x0006000600000000,0x0000000000040004,0x0002000200000000,
0x0002000200000000,0x0000000000040004,0x0006000600000000,0x0000000000080008,0x0008000800000000,0x0000000000060006,0x0004000400000000,0x0000000000020002,
0x0000000000020002,0x0004000400000000,0x0000000000060006,0x0008000800000000,0x0000000000080008,0x0006000600000000,0x0000000000040004,0x0002000200000000,
0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000}
Note that this is not the same as IPPOLIT/IvanHoe, though it is vaguely close. The second table is just double the values in the first.

Code: Select all

static const uint8 BlockedPawnValue[64] =
{ 0, 0, 0, 0, 0, 0, 0, 0,
  1, 1, 2, 2, 2, 2, 1, 1,
  1, 2, 3, 3, 3, 3, 2, 1,
  1, 2, 3, 5, 5, 3, 2, 1,
  1, 2, 3, 5, 5, 3, 2, 1,
  1, 2, 3, 3, 3, 3, 2, 1,
  1, 1, 2, 2, 2, 2, 1, 1,
  0, 0, 0, 0, 0, 0, 0, 0
};
Some technical differences are the four 16-bit fields of Rybka (actually it is two 32-bit fields split on colour, and then the two 16-bit fields in these corresponding to opening/endgame), and how colour is considered.

In the white pawn loop, when checking a pawn on square X Rybka checks if the square in front of X has a pawn (either colour), and if so uses the "double-value" table.

Code: Select all

0x04848dd:     mov    0x2cab40(%r8,%r9,4),%eax   # get piece on sq in front
0x04848e5:     and    $0xe,%al                   # strip off low bit
0x04848e7:     cmp    $0x2,%al                   # see if is pawn (2=w, 3=b)
0x04848e9:     jne    0x4848f9                   # if not jump
0x04848eb:     mov    0x189510(%r8,%r9,8),%rax   # if so use 0x189510 table
0x04848f3:     add    %rax,0x8(%rbx)             # add to current value
0x04848f7:     jmp    0x484905                   # skip to next
0x04848f9:     mov    0x189110(%r8,%r9,8),%rax   # if not use 0x189110 table
0x0484901:     add    %rax,0x8(%rbx)             # add to current value
[Incidentally, the compiler might do better with cmov here as opposed to branching?]

Comparatively, this part of the white pawn loop in IvanHoe looks like:

Code: Select all

      if (SqSet[b] & LIGHT)
        {
          RESULT->wPlight += BlockedPawnValue[b];
          if (POSITION->sq[b + 8] == bEnumP)
            RESULT->wPlight += BlockedPawnValue[b];
        }
      else
        {
          RESULT->wPdark += BlockedPawnValue[b];
          if (POSITION->sq[b + 8] == bEnumP)
            RESULT->wPdark += BlockedPawnValue[b];
        }
So again there is a doubling, but only if the pawn is of the other colour.

Back in the evaluation function, Rybka unpacks the above numbers into four, getting essentially the corresponding items to wPlight and such of IvanHoe.

Code: Select all

0x0463e6b:     mov    0x8(%rax),%r8       # white light/dark
0x0463e89:     mov    0x8(%rax),%eax      # lower 32 bits
0x0463e7f:     shr    $0x20,%r8           # upper 32 bits
0x0463e67:     mov    0x10(%rax),%rdx     # similarly for black
0x0463e86:     mov    0x10(%rax),%ecx
0x0463e7b:     shr    $0x20,%rdx
0x0463e90:     mov    %rdx,0x80(%rsp)     # save all four for future usage
0x0463eb6:     mov    %r8,0x68(%rsp)
0x0463e9b:     mov    %eax,0x2c(%rsp)
0x0463f09:     mov    %ecx,0x70(%rsp)
The totality of these is then summed and doubled to get a VALUE, and for each White bishop VALUE is then subtracted (this occurs in the bishop evaluation loop), with it being added for Black bishops.

Code: Select all

0x0463e8c:     lea    (%rdx,%r8,1),%r12d   # add the values
0x0463e98:     add    %eax,%r12d
0x0463ef3:     add    %ecx,%r12d
0x0463f10:     mov    %r12d,0xa0(%rsp)     # and save it
[...]
0x046446c:     lea    (%r12,%r12,1),%r15d  # double the value
0x046443c:     mov    2517005(%rip),%r13   # 0x6cac50 [white bishops]
0x046447a:     bsf    %r13,%r14            # loop over them
0x0464484:     sub    %r15,%rsi            # subtract the value
[...]
0x0465303:     mov    0xa0(%rsp),%eax      # load this value
0x046530d:     lea    (%rax,%rax,1),%ecx   # double it
0x04652d5:     mov    2513276(%rip),%r13   # 0x6cac58 [black bishops]
0x046533e:     bsf    %r13,%r14            # loop over them
0x0465342:     add    %rcx,%rsi            # add the value...
At that point, the only consideration is for centrality of pawns with respect to bishops. I don't see anything like this in IvanHoe, though there may be alternative compensations with general mobility and/or static bishop values.

Then at the end there is a consideration specifically with colour: if the White bishop bitboard ANDed with the light squares is nonzero, and also with the black squares (in other words, if White has a bishop of each colour, though I say it like this to emphasise the method of calculation), then there is a penalty of twice 2*ABS(WhiteDark-WhiteLight)+ABS(BlackDark-BlackLight). Similarly, if Black has a bishop of each colour, a penalty is added.

Code: Select all

0x046629b:     mov    2509230(%rip),%r11         # 0x6cac50 load White bishops
0x04662a2:     mov    $0x55aa55aa55aa55aa,%rax   # load light squares mask
0x04662ac:     mov    %r11,%r10
0x04662af:     and    %rax,%r10
0x04662b2:     je     0x466325                   # if no light bishop, skip
0x04662b4:     mov    $0xaa55aa55aa55aa55,%rax
0x04662be:     test   %r11,%rax
0x04662c1:     je     0x46631e                   # if no dark bishop, skip
0x04662c3:     mov    0x68(%rsp),%rax            # reload the saved values
0x04662c8:     mov    0x2c(%rsp),%ecx
0x04662cc:     mov    0x70(%rsp),%r13d
0x04662d1:     mov    0x80(%rsp),%r9
0x04662d9:     cmp    %ecx,%eax                  # compute a bunch of ABS
0x04662db:     mov    %ecx,%r8d
0x04662de:     mov    %ecx,%edx
0x04662e0:     cmovg  %eax,%edx
0x04662e3:     cmp    %ecx,%eax
0x04662e5:     mov    %r13d,%ecx
0x04662e8:     cmovl  %eax,%r8d
0x04662ec:     cmp    %r13d,%r9d
0x04662ef:     mov    %r13d,%eax
0x04662f2:     cmovg  %r9d,%ecx
0x04662f6:     cmp    %r13d,%r9d
0x04662f9:     cmovl  %r9d,%eax
0x04662fd:     sub    %edx,%r8d                  # do the maths
0x0466300:     add    %r8d,%r8d
0x0466303:     sub    %ecx,%r8d
0x0466306:     add    %eax,%r8d
0x0466309:     lea    (%r8,%r8,1),%eax           # double it
0x046630d:     cltq
0x046630f:     add    %rax,%rsi                  # add to other eval
When White has a light bishop and no dark bishop, then a bonus (for White) of twice 4*(WhiteDark-WhiteLight)+(BlackDark-BlackLight), is added and similarly when switiching light/dark and Black/White.

Code: Select all

0x04663b5:     mov    $0xaa55aa55aa55aa55,%rax    # black squares mask
0x04663bf:     test   %r11,%rax                   # r11 still has White bishops
0x04663ce:     mov    0x2c(%rsp),%eax
0x04663d2:     mov    0x68(%rsp),%r8
0x04663d7:     mov    0x80(%rsp),%rdx
0x04663df:     sub    %r8d,%eax                   # subtract [0x2c]-[0x68]
0x04663e2:     shl    $0x2,%eax                   # multiply by 4
0x04663e5:     sub    %edx,%eax                   # subtract (0x80)rsp
0x04663e7:     add    %r13d,%eax                  # r13 still has 0x70(rsp)
0x04663ea:     add    %eax,%eax                   # double it
[...]
Rybka also has some differences in "skeletal" mobility of bishops, but I don't think those are as important for this comparison (as they depend on the exact bishop square and current mobility, and not just the colour).

Switching to IvanHoe, the only consideration of PAWN_INFO->wPlight appears to be in the bishop evaluation loops, and the bonus/penalty for light White bishops is:

Code: Select all

     if (SqSet[b] & LIGHT)
        {
          Value -= (PAWN_INFO->wPlight + PAWN_INFO->bPlight / 2) * SCORE (1, 1);
          Value += POPCNT (bBitboardP & LIGHT & InFrontB[RANK (b)] & ~bPatt) * SCORE (0, 2);
        }
and similarly in the other 3 cases.

In particular, the penalty has different weightings (note too that Rybka is in millipawns), and there is also a bonus in the endgame when a bishop is behind enemy pawns that are not guarded by another pawn.

As a demonstration, if I computed this correctly, when there is a a6-b5-c6 f5-e6 g7-h6 chain of Black pawns and a3-b4 d4-e5-f4-g3 for White, I get

Code: Select all

        R3 IH
bPlight 22 20 (1+4+3+8+6) vs (1+4+3+6+6)
bPdark   3  2 (2+1) vs (1+1)
wPlight  0  0
wPdark  25 28 (1+4+4+8+6+2) vs (1+4+5+10+6+2)
As I say, the main difference is in applying these. Assuming both sides have a light squared bishop, Rybka would gives White a bonus of 2*(4*(25-0)+(3-22))=162 and Black a "bonus" of -2*((0-25)+4*(22-3))=-102, for a total of 264 millipawns (this is also just 2*(4-1)*((25-0)+(22-3) in this case). IvanHoe would penalise White at 10 centipawns and Black at 20 centipawns, and so the overall effect is 10 centipawns for White, I think.

As I've commented earlier, LK was happier with Rybka's method, and indeed it tends to give larger adjustments in my experience. In particular in the above, one gets that Rybka's adjustment is typically 6/10 times the sum of the pawn colour differentials when both sides have a single bishop of the same colour, while in IPPOLIT/IvanHoe it would be closer to just 1/2 the amount for one of the colours. The elements of a comparison can change when the bishop situation differs, but I think this is the general flavour.

As for the question of who handles this better, 10 or 25 centipawns might not seem like much to penalise a bad bishop, but it must be recalled that this is on top of other considerations (for instance, a bad bishop will typically have lower mobility). I don't see any answer to this other than to actually test it.

Re: Bad/good bishops in R3 and IPPOLIT/IvanHoe

Posted: Wed Dec 01, 2010 10:32 pm
by BB+
In searching for something else, I found that Osipov was unsure that good/bad bishops were considered in R3. I find LK's comment to be the more correct. http://talkchess.com/forum/viewtopic.ph ... 78&t=31708

Re: Bad/good bishops in R3 and IPPOLIT/IvanHoe

Posted: Thu Dec 02, 2010 1:51 pm
by jury_osipov
BB+ wrote:In searching for something else, I found that Osipov was unsure that good/bad bishops were considered in R3. I find LK's comment to be the more correct. http://talkchess.com/forum/viewtopic.ph ... 78&t=31708
Thanks, BB+!
I also found a good/bad bishop evaluation in the Rybka 3.
Previously, I was looking for it in the bishops loop. It turned out that this evaluation is after all the cycles at the end of the evaluation function.