Announcement: The Bozochess Project

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Details of the high speed check marker

Post by sje »

Here's a brief description of the details of the high speed check marker:

First, there is a "runway" type:

Code: Select all

    { Check detection runway }

    runwaytype =
      record
        prwbb: bbtype; { Landing runway for pawn attackers }
        nrwbb: bbtype; { Landing runway for knight attackers }
        brwbb: bbtype; { Landing runway for bishop attackers }
        rrwbb: bbtype; { Landing runway for rook attackers }
        qrwbb: bbtype; { Landing runway for queen attackers }
        disbb: bbtype  { Discovery candidates }
      end;
To build a runway from a position:

Code: Select all

  procedure PosBuildRunway(var pos: postype; var runway: runwaytype);
    var
      evilkingsq: sqtype;
      dir: dirtype;
      scansq: sqxtype;
      scanindex: Integer;
      stopped: Boolean;
      color: colortype;
      goodsweepbb: bbtype;
      scanbb: bbtype;
  begin
    with pos, board, bbdb, runway do
      begin
        BbReset(disbb); evilkingsq := ksqv[evil]; BbAnd2(goodsweepbb, sweep, locbc[good]);

        { Pawn runway }

        prwbb := pawnatkbbvec[evil, evilkingsq];

        { Knight runway }

        nrwbb := knightatkbbvec[evilkingsq];

        { Bishop runway }

        BbReset(brwbb);
        for dir := dirne to dirse do
          begin
            scanindex := scanmap[evilkingsq, dir]; stopped := False;
            repeat
              scansq := scansqs[scanindex]; Inc(scanindex);
              if scansq = sqnil then stopped := True
              else
                begin
                  color := mantocolor[sqv[scansq]];
                  if color = colorv then BBSetSq(brwbb, scansq)
                  else
                    begin
                      stopped := True;
                      if color = evil then BBSetSq(brwbb, scansq) else BBSetSq(disbb, scansq)
                    end
                end
            until stopped
          end;

        { Rook runway }

        BbReset(rrwbb);
        for dir := dire to dirs do
          begin
            scanindex := scanmap[evilkingsq, dir]; stopped := False;
            repeat
              scansq := scansqs[scanindex]; Inc(scanindex);
              if scansq = sqnil then stopped := True
              else
                begin
                  color := mantocolor[sqv[scansq]];
                  if color = colorv then BBSetSq(rrwbb, scansq)
                  else
                    begin
                      stopped := True;
                      if color = evil then BBSetSq(rrwbb, scansq) else BBSetSq(disbb, scansq)
                    end
                end
            until stopped
          end;

        { Queen runway }

        BbIor2(qrwbb, brwbb, rrwbb);

        { Discovery runway, second pass }

        scanbb := disbb;
        repeat
          scansq := BbNextSq(scanbb);
          if scansq <> sqnil then
            if BbNI3&#40;goodsweepbb, beambbvec&#91;evilkingsq, scansq&#93;, atkts&#91;scansq&#93;) then
              BbResetSq&#40;disbb, scansq&#41;
        until scansq = sqnil

      end
  end; &#123; PosBuildRunway &#125;
And then to mark checking moves without executing them:

Code: Select all

  procedure PosAssignMoveCheckFlags&#40;var pos&#58; postype; var gms&#58; gmstype&#41;;
    var
      evilkingsq&#58; sqtype;
      index&#58; Integer;
      runway&#58; runwaytype;
      check&#58; Boolean;
      hfrsq&#58; sqxtype;
      frpiece&#58; piecetype;
      disco&#58; Boolean;
      beambb&#58; bbtype;
  begin
    with pos, bbdb, gms, runway do
      begin
        PosBuildRunway&#40;pos, runway&#41;; evilkingsq &#58;= ksqv&#91;evil&#93;;
        hfrsq &#58;= sqnil; frpiece &#58;= piecev; disco &#58;= False; BbReset&#40;beambb&#41;;
        for index &#58;= 0 to movecount - 1 do
          with moves&#91;index&#93; do
            begin

              &#123; Set up for a new move &#125;

              check &#58;= False;
              if hfrsq <> frsq then
                begin
                  hfrsq &#58;= frsq; frpiece &#58;= mantopiece&#91;frman&#93;;
                  disco &#58;= BbTestSq&#40;disbb, frsq&#41;; beambb &#58;= beambbvec&#91;evilkingsq, frsq&#93;
                end;

              &#123; Process by moving piece kind &#125;

              case frpiece of
                piecep&#58;
                  case msc of
                    mscreg&#58;
                      if BbTestSq&#40;prwbb, tosq&#41; then check &#58;= True
                      else
                        if disco and &#40;not BbTestSq&#40;beambb, tosq&#41;) then check &#58;= True;
                    mscepc&#58; if PosIsEnPassantMoveChecking&#40;pos, moves&#91;index&#93;) then check &#58;= True;
                    mscppn&#58; if disco or BbTestSq&#40;nrwbb, tosq&#41; then check &#58;= True;
                    mscppb&#58;
                      if disco or BbTestSq&#40;brwbb, tosq&#41; then check &#58;= True
                      else
                        if toman <> manvv then
                          if compass&#91;frsq, tosq&#93; = compass&#91;evilkingsq, frsq&#93; then
                            if BbNI2&#40;merge, pathwaybbvec&#91;evilkingsq, frsq&#93;) then check &#58;= True;
                    mscppr&#58;
                      if disco or BbTestSq&#40;rrwbb, tosq&#41; then check &#58;= True
                      else
                        if toman = manvv then
                          if compass&#91;frsq, tosq&#93; = compass&#91;evilkingsq, frsq&#93; then
                            if BbNI2&#40;merge, pathwaybbvec&#91;evilkingsq, frsq&#93;) then check &#58;= True;
                    mscppq&#58;
                      if disco or BbTestSq&#40;qrwbb, tosq&#41; then check &#58;= True
                      else
                        if compass&#91;frsq, tosq&#93; = compass&#91;evilkingsq, frsq&#93; then
                          if BbNI2&#40;merge, pathwaybbvec&#91;evilkingsq, frsq&#93;) then check &#58;= True
                  end; &#123; case &#125;
                piecen&#58; if disco or BbTestSq&#40;nrwbb, tosq&#41; then check &#58;= True;
                pieceb&#58; if disco or BbTestSq&#40;brwbb, tosq&#41; then check &#58;= True;
                piecer&#58; if disco or BbTestSq&#40;rrwbb, tosq&#41; then check &#58;= True;
                pieceq&#58; if BbTestSq&#40;qrwbb, tosq&#41; then check &#58;= True;
                piecek&#58;
                  case msc of
                    mscreg&#58; if disco and &#40;not BbTestSq&#40;beambb, tosq&#41;) then check &#58;= True;
                    msccqs, msccks&#58;
                      if PosIsCastlingChecking&#40;pos, MapColorMscToCastling&#40;good, msc&#41;) then check &#58;= True
                  end &#123; case &#125;
              end; &#123; case &#125;
              if check then MoveFlagSet&#40;moves&#91;index&#93;, mfchck&#41;
            end
      end
  end; &#123; PosAssignMoveCheckFlags &#125;
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: The current command set

Post by sje »

sje wrote: The "mate" command does correctly report if there is a mate in N, but not very efficiently nor does it give the PV.

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52
&#91;&#93; mate 1
Node count&#58; 5
Predicted score&#58; Even
&#91;&#93; mate 2
Node count&#58; 369
Predicted score&#58; Even
&#91;&#93; mate 3
Node count&#58; 34224
Predicted score&#58; Even
&#91;&#93; mate 4
Node count&#58; 645271
Predicted score&#58; MateIn4
That was then; this is now:

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52
&#91;&#93; mate 4
Found mate in 4
PV&#58; Qe4 g2 Nd6+ Rxd6 Qxe5+ Kf8 Qh8#
Node count&#58; 645271
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49
&#91;&#93; mate 4
Found mate in 4
PV&#58; Raxd1+ Kc2 Qxc4+ Kxb2 Rb1+ Kxa3 Qb3#
Node count&#58; 38262
The node counts are high in part because of a total absence of move ordering heuristics.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: The current command set

Post by sje »

sje wrote: That was then; this is now:

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52
&#91;&#93; mate 4
Found mate in 4
PV&#58; Qe4 g2 Nd6+ Rxd6 Qxe5+ Kf8 Qh8#
Node count&#58; 645271
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49
&#91;&#93; mate 4
Found mate in 4
PV&#58; Raxd1+ Kc2 Qxc4+ Kxb2 Rb1+ Kxa3 Qb3#
Node count&#58; 38262
The node counts are high in part because of a total absence of move ordering heuristics.
I forgot to add the move numbering, so let's try again:

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 52 Qe4 g2 53 Nd6+ Rxd6 54 Qxe5+ Kf8 55 Qh8#
Node count&#58; 645271
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 49 Raxd1+ Kc2 50 Qxc4+ Kxb2 51 Rb1+ Kxa3 52 Qb3#
Node count&#58; 38262
&#91;&#93; sfen 1B6/6k1/8/4pB2/7Q/3r4/2K5/3Q2q1 b - - 3 99
&#91;&#93; mate 4 
Found mate in 4
PV&#58; 99... Qxd1+ 100 Kb2 Qd2+ 101 Ka1 Qc1+ 102 Ka2 Ra3#
Node count&#58; 1904
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: The current command set

Post by sje »

sje wrote:The node counts are high in part because of a total absence of move ordering heuristics.

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 52 Qe4 g2 53 Nd6+ Rxd6 54 Qxe5+ Kf8 55 Qh8#
Node count&#58; 645271
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 49 Raxd1+ Kc2 50 Qxc4+ Kxb2 51 Rb1+ Kxa3 52 Qb3#
Node count&#58; 38262
&#91;&#93; sfen 1B6/6k1/8/4pB2/7Q/3r4/2K5/3Q2q1 b - - 3 99
&#91;&#93; mate 4 
Found mate in 4
PV&#58; 99... Qxd1+ 100 Kb2 Qd2+ 101 Ka1 Qc1+ 102 Ka2 Ra3#
Node count&#58; 1904
Now with slow but effective move ordering:

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52
&#91;&#93; mate 4
Found mate in 4
PV&#58; 52 Rh8+ Ke7 53 Qh7+ Kf6 54 Qg6+ Ke7 55 Qg7#
Node count&#58; 9193
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49
&#91;&#93; mate 4
Found mate in 4
PV&#58; 49 Raxd1+ Kc2 50 Qxc4+ Kxb2 51 Rb1+ Kxa3 52 Qb3#
Node count&#58; 386
&#91;&#93; sfen 1B6/6k1/8/4pB2/7Q/3r4/2K5/3Q2q1 b - - 3 99 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 99... Qxd1+ 100 Kb2 Qd2+ 101 Ka1 Qc1+ 102 Ka2 Ra3#
Node count&#58; 303
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

The rather simple mate finder routine

Post by sje »

The rather simple mate finder routine:

Code: Select all

  procedure CpcFindMate&#40;var cpc&#58; cpctype; fullmovecount&#58; Integer&#41;;
    var
      ply&#58; plytype;
      depth&#58; Integer;
      rootwindow&#58; windowtype;

    function MateDefend&#40;var mywindow&#58; windowtype; var mypv&#58; variationtype&#41;&#58; svtype; forward;

    function MateAttack&#40;var mywindow&#58; windowtype; var mypv&#58; variationtype&#41;&#58; svtype;
      var
        gms&#58; gmstype;
        index&#58; Integer;
        subwindow&#58; windowtype;
        subpv&#58; variationtype;
        subsv&#58; svtype;
    begin
      with cpc, gms do
        begin
          Inc&#40;sr.nc&#41;;
          VariationInit&#40;subpv&#41;;
          if depth = 1 then PosGenOnlyChecks&#40;pos, gms&#41;
          else
            begin
              PosGenerate&#40;pos, gms&#41;; PosApplyOrderAntiMobility&#40;pos, gms&#41;; GmsSortByScore&#40;gms&#41;
            end;
          index &#58;= 0;
          while &#40;index < movecount&#41; and
              WindowIsOpen&#40;mywindow&#41; and
              &#40;not IsSvMating&#40;mywindow.alfa&#41;) do
            begin
              WindowShiftDn&#40;mywindow, subwindow&#41;; VariationRecycle&#40;subpv&#41;;
              PosExecute&#40;pos, moves&#91;index&#93;); Inc&#40;ply&#41;; Dec&#40;depth&#41;;
              subsv &#58;= CalcSvUp&#40;MateDefend&#40;subwindow, subpv&#41;);
              PosRetract&#40;pos&#41;; Dec&#40;ply&#41;; Inc&#40;depth&#41;;
              if subsv > mywindow.alfa then
                begin
                  mywindow.alfa &#58;= subsv;
                  if subsv < mywindow.beta then
                    begin
                      VariationRecycle&#40;mypv&#41;;
                      VariationAppendMove&#40;mypv, moves&#91;index&#93;);
                      VariationAppend&#40;mypv, subpv&#41;
                    end
                end;
              Inc&#40;index&#41;
            end;
          VariationTerm&#40;subpv&#41;
        end;
      MateAttack &#58;= mywindow.alfa
    end; &#123; MateAttack &#125;

    function MateDefend&#40;var mywindow&#58; windowtype; var mypv&#58; variationtype&#41;&#58; svtype;
      var
        gms&#58; gmstype;
        index&#58; Integer;
        subwindow&#58; windowtype;
        subpv&#58; variationtype;
        subsv&#58; svtype;
    begin
      with cpc, gms do
        begin
          Inc&#40;sr.nc&#41;;
          if depth = 0 then
            if PosIsCheckmate&#40;pos&#41; then mywindow.alfa &#58;= svlosein0 else mywindow.alfa &#58;= sveven
          else
            begin
              PosGenerate&#40;pos, gms&#41;;
              if movecount = 0 then
                if pos.inch then mywindow.alfa &#58;= svlosein0 else mywindow.alfa &#58;= sveven
              else
                begin
                  VariationInit&#40;subpv&#41;;
                  PosApplyOrderAntiMobility&#40;pos, gms&#41;; GmsSortByScore&#40;gms&#41;;
                  index &#58;= 0;
                  while &#40;index < movecount&#41; and
                      WindowIsOpen&#40;mywindow&#41; and
                      IsSvLosing&#40;mywindow.alfa&#41; do
                    begin
                      WindowShiftDn&#40;mywindow, subwindow&#41;; VariationRecycle&#40;subpv&#41;;
                      PosExecute&#40;pos, moves&#91;index&#93;); Inc&#40;ply&#41;; Dec&#40;depth&#41;;
                      subsv &#58;= CalcSvUp&#40;MateAttack&#40;subwindow, subpv&#41;);
                      PosRetract&#40;pos&#41;; Dec&#40;ply&#41;; Inc&#40;depth&#41;;
                      if subsv > mywindow.alfa then
                        begin
                          mywindow.alfa &#58;= subsv;
                          if subsv < mywindow.beta then
                            begin
                              VariationRecycle&#40;mypv&#41;;
                              VariationAppendMove&#40;mypv, moves&#91;index&#93;);
                              VariationAppend&#40;mypv, subpv&#41;
                            end
                        end;
                      Inc&#40;index&#41;
                    end;
                  VariationTerm&#40;subpv&#41;
                end
            end
        end;
      MateDefend &#58;= mywindow.alfa
    end; &#123; MateDefend &#125;

  begin
    with cpc, sr do
      begin
        SrReset&#40;sr&#41;; ply &#58;= 0; depth &#58;= &#40;fullmovecount * 2&#41; - 1;
        rootwindow.alfa &#58;= sveven - 1; rootwindow.beta &#58;= SynthMateInN&#40;0&#41;;
        ps &#58;= MateAttack&#40;rootwindow, pv&#41;; VariationNotate&#40;pv, pos&#41;
      end
  end; &#123; CpcFindMate &#125;
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: The current command set

Post by sje »

sje wrote: Now with slow but effective move ordering:

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52
&#91;&#93; mate 4
Found mate in 4
PV&#58; 52 Rh8+ Ke7 53 Qh7+ Kf6 54 Qg6+ Ke7 55 Qg7#
Node count&#58; 9193
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49
&#91;&#93; mate 4
Found mate in 4
PV&#58; 49 Raxd1+ Kc2 50 Qxc4+ Kxb2 51 Rb1+ Kxa3 52 Qb3#
Node count&#58; 386
&#91;&#93; sfen 1B6/6k1/8/4pB2/7Q/3r4/2K5/3Q2q1 b - - 3 99 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 99... Qxd1+ 100 Kb2 Qd2+ 101 Ka1 Qc1+ 102 Ka2 Ra3#
Node count&#58; 303
Even better, now with elapsed time (DDD.HH:MM:SS.mmm):

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 52 Rh8+ Ke7 53 Qh7+ Kf6 54 Qg6+ Ke7 55 Qg7#
Node count&#58; 9193
Elapsed time&#58; 000.00&#58;00&#58;00.318
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 49 Raxd1+ Kc2 50 Qxc4+ Kxb2 51 Rb1+ Kxa3 52 Qb3#
Node count&#58; 386
Elapsed time&#58; 000.00&#58;00&#58;00.019
&#91;&#93; sfen 1B6/6k1/8/4pB2/7Q/3r4/2K5/3Q2q1 b - - 3 99
&#91;&#93; mate 4
Found mate in 4
PV&#58; 99... Qxd1+ 100 Kb2 Qd2+ 101 Ka1 Qc1+ 102 Ka2 Ra3#
Node count&#58; 303
Elapsed time&#58; 000.00&#58;00&#58;00.021
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Some speed improvements

Post by sje »

There have been some speed improvements with the underlying bitboard database manipulation. There can be more of these, but only at the cost for adding too much mystery for a pedagogical program.

Code: Select all

&#91;&#93; sfen 1B1bk3/7R/1r5p/1Pp1p3/2NP1N2/1RP2Pp1/2QK4/8 w - - 2 52 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 52 Rh8+ Ke7 53 Qh7+ Kf6 54 Qg6+ Ke7 55 Qg7#
Count&#58; 9193   Time&#58; 000.00&#58;00&#58;00.148   Frequency&#58; 62114
&#91;&#93; sfen 1B6/2r5/8/p1bQ4/2p1P1Pp/P2P3P/1P1k2BK/R2b1R2 w - - 5 49 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 49 Raxd1+ Kc2 50 Qxc4+ Kxb2 51 Rb1+ Kxa3 52 Qb3#
Count&#58; 386   Time&#58; 000.00&#58;00&#58;00.009   Frequency&#58; 42888
&#91;&#93; sfen 1B6/6k1/8/4pB2/7Q/3r4/2K5/3Q2q1 b - - 3 99 
&#91;&#93; mate 4
Found mate in 4
PV&#58; 99... Qxd1+ 100 Kb2 Qd2+ 101 Ka1 Qc1+ 102 Ka2 Ra3#
Count&#58; 303   Time&#58; 000.00&#58;00&#58;00.009   Frequency&#58; 33666
&#91;&#93; perftfull 7
Depth&#58; 7
FEN&#58; rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
  Na3 120142144
  Nc3 148527161
  Nf3 147678554
  Nh3 120669525
  a3 106743106
  a4 137077337
  b3 133233975
  b4 134087476
  c3 144074944
  c4 157756443
  d3 227598692
  d4 269605599
  e3 306138410
  e4 309478263
  f3 102021008
  f4 119614841
  g3 135987651
  g4 130293018
  h3 106678423
  h4 138495290
Count&#58; 3195901860   Time&#58; 000.01&#58;04&#58;57.160   Frequency&#58; 820059
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: Some speed improvements

Post by sje »

sje wrote:

Code: Select all

&#91;&#93; perftfull 7
Depth&#58; 7
FEN&#58; rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
  Na3 120142144
  Nc3 148527161
  Nf3 147678554
  Nh3 120669525
  a3 106743106
  a4 137077337
  b3 133233975
  b4 134087476
  c3 144074944
  c4 157756443
  d3 227598692
  d4 269605599
  e3 306138410
  e4 309478263
  f3 102021008
  f4 119614841
  g3 135987651
  g4 130293018
  h3 106678423
  h4 138495290
Count&#58; 3195901860   Time&#58; 000.01&#58;04&#58;57.160   Frequency&#58; 820059
The above perft included a visit to each terminal node with a full update/downdate of all position data. Bulk counting and bulk counting with transposition assist (2^20 entry table) are rather faster:

Code: Select all

&#91;&#93; perftbulk 7
Depth&#58; 7
FEN&#58; rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
  Na3 120142144
  Nc3 148527161
  Nf3 147678554
  Nh3 120669525
  a3 106743106
  a4 137077337
  b3 133233975
  b4 134087476
  c3 144074944
  c4 157756443
  d3 227598692
  d4 269605599
  e3 306138410
  e4 309478263
  f3 102021008
  f4 119614841
  g3 135987651
  g4 130293018
  h3 106678423
  h4 138495290
Count&#58; 3195901860   Time&#58; 000.00&#58;03&#58;51.147   Frequency&#58; 13826274
&#91;&#93; perfttran 7
Depth&#58; 7
FEN&#58; rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
  Na3 120142144
  Nc3 148527161
  Nf3 147678554
  Nh3 120669525
  a3 106743106
  a4 137077337
  b3 133233975
  b4 134087476
  c3 144074944
  c4 157756443
  d3 227598692
  d4 269605599
  e3 306138410
  e4 309478263
  f3 102021008
  f4 119614841
  g3 135987651
  g4 130293018
  h3 106678423
  h4 138495290
Count&#58; 3195901860   Time&#58; 000.00&#58;00&#58;45.897   Frequency&#58; 69632042
All calculations have been done using a single thread. This will likely change, but not today.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

The benchmark position

Post by sje »

At the present, Bozo has only a single position in use for benchmark generation, and the benchmark is a simple "visit all nodes" perft. This position is:
[d]r3r1k1/1ppq1ppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PPQ1PPP/R3R1K1 w - - 0 11[/d]
The above position was chosen in part because it is color-symmetric, fairly complex, and thoroughly exercises the bitboard database subsystem.

Perft(1): 46
Perft(2): 2,080
Perft(3): 91,826
Perft(4): 4,062,390 (this draft is the one used by the "bench" command)
Perft(5): 176,639,308
Perft(6): 7,687,471,123
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Two for the price of one

Post by sje »

That's changing the from and to square location data in a bitboard database for the same price as changing only one of them. The idea is to have an array of constant bitboards, each with TWO bits set.

Easier to read the code than to read the explanation:

Code: Select all

  procedure BbdbLocusToggle&#40;var bbdb&#58; bbdbtype; man&#58; manrtype; sq&#58; sqtype&#41;;
    var
      bb&#58; bbtype;
  begin
    with bbdb do
      begin
        bb &#58;= singlebitbbvec&#91;sq&#93;;
        BbXor2D&#40;merge, bb&#41;; BbXor2D&#40;locbc&#91;mantocolor&#91;man&#93;&#93;, bb&#41;; BbXor2D&#40;locbm&#91;man&#93;, bb&#41;;
        if man in sweepermanset then BbXor2D&#40;sweep, bb&#41;
      end
  end; &#123; BbdbLocusToggle &#125;

  procedure BbdbLocusChange&#40;var bbdb&#58; bbdbtype; man&#58; manrtype; frsq, tosq&#58; sqtype&#41;;
    var
      bb&#58; bbtype;
  begin
    with bbdb do
      begin
        bb &#58;= doublebitbbvec&#91;frsq, tosq&#93;;
        BbXor2D&#40;merge, bb&#41;; BbXor2D&#40;locbc&#91;mantocolor&#91;man&#93;&#93;, bb&#41;; BbXor2D&#40;locbm&#91;man&#93;, bb&#41;;
        if man in sweepermanset then BbXor2D&#40;sweep, bb&#41;
      end
  end; &#123; BbdbLocusChange &#125;

  procedure BbdbAddMan&#40;var bbdb&#58; bbdbtype; man&#58; manrtype; sq&#58; sqtype&#41;;
  begin

    &#123; Locus update &#125;

    BbdbLocusToggle&#40;bbdb, man, sq&#41;;

    &#123; Attack update &#125;

    BbdbCutAttacks&#40;bbdb, sq&#41;;
    BbdbAddAttacks&#40;bbdb, sq, man&#41;

  end; &#123; BbdbAddMan &#125;

  procedure BbdbDelMan&#40;var bbdb&#58; bbdbtype; man&#58; manrtype; sq&#58; sqtype&#41;;
  begin

    &#123; Locus update &#125;

    BbdbLocusToggle&#40;bbdb, man, sq&#41;;

    &#123; Attack update &#125;

    BbdbDelAttacks&#40;bbdb, sq, man&#41;;
    BbdbProAttacks&#40;bbdb, sq&#41;

  end; &#123; BbdbDelMan &#125;

  procedure BbdbMovMan&#40;var bbdb&#58; bbdbtype; man&#58; manrtype; frsq, tosq&#58; sqtype&#41;;
  begin

    &#123; Locus update &#125;

    BbdbLocusChange&#40;bbdb, man, frsq, tosq&#41;;

    &#123; Attack update &#125;

    BbdbDelAttacks&#40;bbdb, frsq, man&#41;;
    BbdbProAttacks&#40;bbdb, frsq&#41;;
    BbdbCutAttacks&#40;bbdb, tosq&#41;;
    BbdbAddAttacks&#40;bbdb, tosq, man&#41;

  end; &#123; BbdbMovMan &#125;

  procedure BbdbCaptureMan&#40;var bbdb&#58; bbdbtype; frman, toman&#58; manrtype; frsq, tosq&#58; sqtype&#41;;
  begin

    &#123; Locus update &#125;

    BbdbLocusToggle&#40;bbdb, toman, tosq&#41;;
    BbdbLocusChange&#40;bbdb, frman, frsq, tosq&#41;;

    &#123; Attack update &#125;

    BbdbDelAttacks&#40;bbdb, tosq, toman&#41;;
    BbdbDelAttacks&#40;bbdb, frsq, frman&#41;;
    BbdbProAttacks&#40;bbdb, frsq&#41;;
    BbdbAddAttacks&#40;bbdb, tosq, frman&#41;

  end; &#123; BbdbCaptureMan &#125;

  procedure BbdbRevCaptMan&#40;var bbdb&#58; bbdbtype; frman, toman&#58; manrtype; frsq, tosq&#58; sqtype&#41;;
  begin

    &#123; Locus update &#125;

    BbdbLocusChange&#40;bbdb, frman, tosq, frsq&#41;;
    BbdbLocusToggle&#40;bbdb, toman, tosq&#41;;

    &#123; Attack update &#125;

    BbdbDelAttacks&#40;bbdb, tosq, frman&#41;;
    BbdbCutAttacks&#40;bbdb, frsq&#41;;
    BbdbAddAttacks&#40;bbdb, frsq, frman&#41;;
    BbdbAddAttacks&#40;bbdb, tosq, toman&#41;

  end; &#123; BbdbRevCaptMan &#125;