LCOV - code coverage report
Current view: top level - src - matsig.h (source / functions) Hit Total Coverage
Test: test_coverage.info Lines: 13 13 100.0 %
Date: 2017-06-21 14:32:49 Functions: 1 1 100.0 %

          Line data    Source code
       1             : //////////////////////////////////////////////////////////////////////
       2             : //
       3             : //  FILE:       matsig.h
       4             : //              Material signatures and home-pawn signatures.
       5             : //
       6             : //  Part of:    Scid (Shane's Chess Information Database)
       7             : //  Version:    1.9
       8             : //
       9             : //  Notice:     Copyright (c) 2000  Shane Hudson.  All rights reserved.
      10             : //
      11             : //  Author:     Shane Hudson (sgh@users.sourceforge.net)
      12             : //
      13             : //////////////////////////////////////////////////////////////////////
      14             : 
      15             : 
      16             : #ifndef SCID_MATSIG_H
      17             : #define SCID_MATSIG_H
      18             : 
      19             : #include "common.h"
      20             : #include <algorithm>
      21             : #include <string>
      22             : 
      23             : // Matsigs are 32-bit unsigned ints.  We only use 24 bits of this.
      24             : 
      25             : typedef uint32_t matSigT;
      26             : 
      27             : // From most significant bits down to least, the matsig layout is:
      28             : // Bits 22-33:  WQ    Bits 10-11:  BQ
      29             : // Bits 20-21:  WN    Bits 08-09:  BR
      30             : // Bits 18-19:  WB    Bits 06-07:  BB
      31             : // Bits 16-17:  WN    Bits 04-05:  BN
      32             : // Bits 12-15:  WP    Bits 00-03:  BP
      33             : 
      34             : // This means that pawn counts from 0 to 8 are possible, but for other
      35             : // pieces only counts up to 3 are possible.
      36             : 
      37             : 
      38             : // Shifts:
      39             : 
      40             : #define SHIFT_BP 0
      41             : #define SHIFT_BN 4
      42             : #define SHIFT_BB 6
      43             : #define SHIFT_BR 8
      44             : #define SHIFT_BQ 10
      45             : #define SHIFT_WP 12
      46             : #define SHIFT_WN 16
      47             : #define SHIFT_WB 18
      48             : #define SHIFT_WR 20
      49             : #define SHIFT_WQ 22
      50             : 
      51             : 
      52             : // Masks:
      53             :                             //         28   24   20   16   12    8    4    0
      54             : #define MASK_BP 0x0000000F  // 0- 3: .... .... .... .... .... .... .... 1111
      55             : #define MASK_BN 0x00000030  // 4- 5: .... .... .... .... .... .... ..11 ....
      56             : #define MASK_BB 0x000000C0  // 6- 7: .... .... .... .... .... .... 11.. ....
      57             : #define MASK_BR 0x00000300  // 8- 9: .... .... .... .... .... ..11 .... ....
      58             : #define MASK_BQ 0x00000C00  //10-11: .... .... .... .... .... 11.. .... ....
      59             : #define MASK_WP 0x0000F000  //12-15: .... .... .... .... 1111 .... .... ....
      60             : #define MASK_WN 0x00030000  //16-17: .... .... .... ..11 .... .... .... ....
      61             : #define MASK_WB 0x000C0000  //18-19: .... .... .... 11.. .... .... .... ....
      62             : #define MASK_WR 0x00300000  //20-21: .... .... ..11 .... .... .... .... ....
      63             : #define MASK_WQ 0x00C00000  //29-31: .... .... 11.. .... .... .... .... ....
      64             : 
      65             : 
      66             : // The arrays MASK_BY_PIECE and SHIFT_BY_PIECE are useful for setting
      67             : // matsigs by piece type:
      68             : 
      69             : const matSigT
      70             : MASK_BY_PIECE [16] = {
      71             :     0,        //  0: Empty
      72             :     0,        //  1: WK
      73             :     MASK_WQ,  //  2: WQ
      74             :     MASK_WR,  //  3: WR
      75             :     MASK_WB,  //  4: WB
      76             :     MASK_WN,  //  5: WN
      77             :     MASK_WP,  //  6: WP
      78             :     0, 0,     //  7, 8: Invalid pieces
      79             :     0,        //  9: BK
      80             :     MASK_BQ,  // 10: BQ
      81             :     MASK_BR,  // 11: BR
      82             :     MASK_BB,  // 12: BB
      83             :     MASK_BN,  // 13: BN
      84             :     MASK_BP,  // 14: BP
      85             :     0         // 15: Invalid piece
      86             : };
      87             : 
      88             : const uint
      89             : SHIFT_BY_PIECE[16] = {
      90             :     0, 0,      //  0: Empty,  1: WK
      91             :     SHIFT_WQ,  //  2: WQ
      92             :     SHIFT_WR,  //  3: WR
      93             :     SHIFT_WB,  //  4: WB
      94             :     SHIFT_WN,  //  5: WN
      95             :     SHIFT_WP,  //  6: WP
      96             :     0, 0, 0,   //  7, 8: Invalid pieces,  9: BK
      97             :     SHIFT_BQ,  // 10: BQ
      98             :     SHIFT_BR,  // 11: BR
      99             :     SHIFT_BB,  // 12: BB
     100             :     SHIFT_BN,  // 13: BN
     101             :     SHIFT_BP,  // 14: BP
     102             :     0          // 15: Invalid piece
     103             : };
     104             : 
     105             : 
     106             : // Quick way to flip colors: just switch the upper/lower 12 bits
     107             : 
     108             : #define MATSIG_FlipColor(x) ((x) >> 12) | (((x) & 0x00000FFF) << 12)
     109             : 
     110             : 
     111             : // Quick tests for non-zero counts of a piece type:
     112             : 
     113             : #define MATSIG_Has_WQ(x)  ((x) & MASK_WQ)
     114             : #define MATSIG_Has_BQ(x)  ((x) & MASK_BQ)
     115             : #define MATSIG_Has_WR(x)  ((x) & MASK_WR)
     116             : #define MATSIG_Has_BR(x)  ((x) & MASK_BR)
     117             : #define MATSIG_Has_WB(x)  ((x) & MASK_WB)
     118             : #define MATSIG_Has_BB(x)  ((x) & MASK_BB)
     119             : #define MATSIG_Has_WN(x)  ((x) & MASK_WN)
     120             : #define MATSIG_Has_BN(x)  ((x) & MASK_BN)
     121             : #define MATSIG_Has_WP(x)  ((x) & MASK_WP)
     122             : #define MATSIG_Has_BP(x)  ((x) & MASK_BP)
     123             : 
     124             : #define MATSIG_HasQueens(x)   ((x) & (MASK_WQ | MASK_BQ))
     125             : #define MATSIG_HasRooks(x)    ((x) & (MASK_WR | MASK_BR))
     126             : #define MATSIG_HasBishops(x)  ((x) & (MASK_WB | MASK_BB))
     127             : #define MATSIG_HasKnights(x)  ((x) & (MASK_WN | MASK_BN))
     128             : #define MATSIG_HasPawns(x)    ((x) & (MASK_WP | MASK_BP))
     129             : 
     130             : 
     131             : // Macros to extract a particular count:
     132             : 
     133             : #define MATSIG_Count_WQ(x)  (((x) & MASK_WQ) >> SHIFT_WQ)
     134             : #define MATSIG_Count_BQ(x)  (((x) & MASK_BQ) >> SHIFT_BQ)
     135             : #define MATSIG_Count_WR(x)  (((x) & MASK_WR) >> SHIFT_WR)
     136             : #define MATSIG_Count_BR(x)  (((x) & MASK_BR) >> SHIFT_BR)
     137             : #define MATSIG_Count_WB(x)  (((x) & MASK_WB) >> SHIFT_WB)
     138             : #define MATSIG_Count_BB(x)  (((x) & MASK_BB) >> SHIFT_BB)
     139             : #define MATSIG_Count_WN(x)  (((x) & MASK_WN) >> SHIFT_WN)
     140             : #define MATSIG_Count_BN(x)  (((x) & MASK_BN) >> SHIFT_BN)
     141             : #define MATSIG_Count_WP(x)  (((x) & MASK_WP) >> SHIFT_WP)
     142             : #define MATSIG_Count_BP(x)  (((x) & MASK_BP) >> SHIFT_BP)
     143             : 
     144             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     145             : // matsig_getCount():
     146             : //      Inline routine to extract a count of a certain piece type.
     147             : //
     148             : inline uint
     149             : matsig_getCount (matSigT m, pieceT p)
     150             : {
     151             :     return (m & MASK_BY_PIECE[p]) >> SHIFT_BY_PIECE[p];
     152             : }
     153             : 
     154             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     155             : // matsig_setCount():
     156             : //      Inline routine to set a particular count.
     157             : //
     158             : inline matSigT
     159             : matsig_setCount (matSigT m, pieceT p, uint count)
     160             : {
     161             :     // First we clear the old mask for this piece:
     162             :     m &= ~(MASK_BY_PIECE[p]);
     163             : 
     164             :          // Avoid overflow.
     165             :          if (p != PAWN && count > 3)
     166             :                  count = 3;
     167             : 
     168             :     // Now we OR to add the new value in:
     169             :     m |= ((uint) count) << SHIFT_BY_PIECE[p];
     170             :     return m;
     171             : }
     172             : 
     173             : 
     174             : // Common constant matsigs:
     175             : 
     176             : const matSigT MATSIG_Empty = 0;
     177             : 
     178             : const matSigT MATSIG_StdStart =
     179             :    ((1 << SHIFT_WQ) | (1 << SHIFT_BQ) | (2 << SHIFT_WR) | (2 << SHIFT_BR) |
     180             :     (2 << SHIFT_WB) | (2 << SHIFT_BB) | (2 << SHIFT_WN) | (2 << SHIFT_BN) |
     181             :     (8 << SHIFT_WP) | (8 << SHIFT_BP));
     182             : 
     183             : 
     184             : //
     185             : // Public functions found in matsig.cpp:
     186             : //
     187             : 
     188             : 
     189             : // matsig_makeString: sets s to be a string representation of the sig,
     190             : std::string
     191             : matsig_makeString (matSigT matsig);
     192             : 
     193             : 
     194             : // matsig_isReachable: returns true if a game currently
     195             : //     at a position with the signature <start>, could possibly reach
     196             : //     the signature <target>. This is useful for quick tests for material
     197             : //     searches. For example, if we store the final matsig of every game,
     198             : //     we can speedup a material search by ONLY searching the games that
     199             : //     have matsig_isReachable(searchsig, finalsig) = 1, or have promotions.
     200             : //     Example: if searchsig requires neither side to have queens, but
     201             : //     finalsig for a game shows a WQ (and no promotions), the game could
     202             : //     not possibly match.
     203             : //     If promos is true, only the pawn counts are checked, since other
     204             : //     material could reappear on the board due to a promotion.
     205             : //     If upromo is true, there are underpromotions (to R, B or N) but
     206             : //     if only promos is true, all promotions are to Queens only.
     207             : bool
     208             : matsig_isReachable (matSigT mStart, matSigT mTarget, bool promos, bool upromo);
     209             : 
     210             : // matsig_isReachablePawns:
     211             : //    like matsig_isReachable, but considering pawns only.
     212             : inline bool
     213             : matsig_isReachablePawns (matSigT mStart, matSigT mTarget)
     214             : {
     215             :     if (MATSIG_Count_WP(mStart) < MATSIG_Count_WP(mTarget)) { return false; }
     216             :     if (MATSIG_Count_BP(mStart) < MATSIG_Count_BP(mTarget)) { return false; }
     217             :     return true;
     218             : }
     219             : 
     220             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     221             : // matsig_Make():
     222             : //      Make a material sig, given an array of material counts as
     223             : //      stored in a Position.
     224             : //
     225             : inline matSigT
     226      949126 : matsig_Make (byte * materialCounts)
     227             : {
     228      949126 :     matSigT m = 0;
     229     1898252 :     m |= std::min<matSigT>(3, materialCounts[WQ]) << SHIFT_WQ;
     230     1898252 :     m |= std::min<matSigT>(3, materialCounts[WR]) << SHIFT_WR;
     231     1898252 :     m |= std::min<matSigT>(3, materialCounts[WB]) << SHIFT_WB;
     232     1898252 :     m |= std::min<matSigT>(3, materialCounts[WN]) << SHIFT_WN;
     233      949126 :     m |= matSigT(materialCounts[WP]) << SHIFT_WP;
     234     1898252 :     m |= std::min<matSigT>(3, materialCounts[BQ]) << SHIFT_BQ;
     235     1898252 :     m |= std::min<matSigT>(3, materialCounts[BR]) << SHIFT_BR;
     236     1898252 :     m |= std::min<matSigT>(3, materialCounts[BB]) << SHIFT_BB;
     237     1898252 :     m |= std::min<matSigT>(3, materialCounts[BN]) << SHIFT_BN;
     238      949126 :     m |= matSigT(materialCounts[BP]) << SHIFT_BP;
     239      949126 :     return m;
     240             : }
     241             : 
     242             : 
     243             : // Common HPSigs:
     244             : // 0 => no pawns still on their original 2nd/7th rank squares.
     245             : // 0xFFFF => all 16 pawns still on their original 2nd/7th rank squares.
     246             : 
     247             : const uint
     248             : HPSIG_Empty = 0x0;
     249             : 
     250             : const uint
     251             : HPSIG_StdStart = 0xFFFF;
     252             : 
     253             : 
     254             : bool
     255             : hpSig_PossibleMatch (uint hpSig, const byte * changeList);
     256             : 
     257             : bool
     258             : hpSig_Prefix (const byte * changeListA, const byte * changeListB);
     259             : 
     260             : uint
     261             : hpSig_Final (const byte * changeList);
     262             : 
     263             : // hpSig_bitMask[]: used to add or clear bits in an hpSig.
     264             : //
     265             : static const uint hpSig_bitMask [16] = {
     266             :     // a2 to h2:
     267             :     0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100,
     268             :     // a7 to h7:
     269             :     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
     270             : };
     271             : 
     272             : inline uint
     273             : hpSig_AddPawn (uint hpSig, colorT color, fyleT fyle)
     274             : {
     275             :     ASSERT (color == WHITE  ||  color == BLACK);
     276             :     ASSERT (fyle <= H_FYLE);
     277             : 
     278             :     uint val = (uint) fyle;
     279             :     if (color == BLACK) val += 8;
     280             :     return hpSig | hpSig_bitMask [val];
     281             : }
     282             : 
     283             : inline uint
     284             : hpSig_ClearPawn (uint hpSig, colorT color, fyleT fyle)
     285             : {
     286             :     ASSERT (color == WHITE  ||  color == BLACK);
     287             :     ASSERT (fyle <= H_FYLE);
     288             : 
     289             :     uint val = (uint) fyle;
     290             :     if (color == BLACK) val += 8;
     291             :     return hpSig & ~(hpSig_bitMask [val]);
     292             : }
     293             : 
     294             : 
     295             : #endif
     296             : 
     297             : //////////////////////////////////////////////////////////////////////
     298             : //  EOF: matsig.h
     299             : //////////////////////////////////////////////////////////////////////
     300             : 

Generated by: LCOV version 1.12