Page 1 of 1

Fuit's pawn evaluation using 8-bits ?

PostPosted: 08 Aug 2005, 18:19
by Chan Rasjid
I remember past threads mentioning the pawns.c file of fruit's
with variables/pawn-array names with xxxG, xxxL, xxxGE, xxxLE etc.

I have just figured out that probably fruit is using some sort of 8-bits
bitboard (bitbase ?) to implement evaluation of pawn structure and pawns cover for king safety.I just finished emulating these same evaluation from
TSCP using 8-bit char, 8 bits to represent rank/file 0-7 with 1,2,4,8,...

The method I use is to collect for the least-advanced pawn of each file(and color) the remaining ranks(as bits) that it may pass through ahead. This bitbased method may be more efficient than the way done in TSCP as bitwise operators are used and the codes seems more compact.

I post my 2 files pawn.h and pawns.c and anyone may use them freely and consider them their own if they wish to. I have checked them fairly carefully but my programming skill is only so... so. I am not sure if it's buggy. So let me know if there are bugs.

Can such 8-bits be used for other things ?

Thanks
Rasjid

pawn.h -

#ifndef __pawn_h__
#define __pawn_h__

#define KS_SCORE_WT 64
#define KS_SCORE_DIV 48
#define P_COVER_CENTER_NULL 10
#define P_COVER_MOVED_1 10
#define P_COVER_MOVED_2 15
#define P_COVER_ZERO 24
// pawn storm
#define P_COVER_ZERO_XSIDE 15
#define PAWN_STORM_2 10
#define PAWN_STORM_1 5

// or 12/25
#define DOUBLED_PAWN 10
#define LONE_PAWN 20
#define BACKWARD_PAWN 8
#define PASS_PAWN_PER_RANK 3

typedef char _bb_t;

/*
(bitbase ?) for pawn structure eval :-
8 bits to represent rank/file 0-7 using 1, 2, 4, 8, ...
*/

#define bbE0 (_bb_t) 1
#define bbE1 (_bb_t) 2
#define bbE2 (_bb_t) 4
#define bbE3 (_bb_t) 8
#define bbE4 (_bb_t) 0x10
#define bbE5 (_bb_t) 0x20
#define bbE6 (_bb_t) 0x40
#define bbE7 (_bb_t) 0x80

#define bbG0 (_bb_t) 0376
#define bbG1 (_bb_t) 0374
#define bbG2 (_bb_t) 0370
#define bbG3 (_bb_t) 0360
#define bbG4 (_bb_t) 0340
#define bbG5 (_bb_t) 0300
#define bbG6 (_bb_t) 0200
#define bbG7 (_bb_t) 0


#define bbL0 (_bb_t) 0
#define bbL1 (_bb_t) 1
#define bbL2 (_bb_t) 3
#define bbL3 (_bb_t) 7
#define bbL4 (_bb_t) 017
#define bbL5 (_bb_t) 037
#define bbL6 (_bb_t) 077
#define bbL7 (_bb_t) 0177


//rank/file equal
extern const _bb_t bbE[8];
// bits ahead in rank for color
extern const _bb_t rankG[2][8];

extern _bb_t ladvPRankG[2][8]; //[col][file] for least advance pawns of color and file
extern _bb_t ladvPRankGSide[2][8];// OR of the 2 side files
extern int (*evalPawn[2])(PPC );
extern int max_pawn[2], p_score[2], ks_score[2];

int bPawn(PPC p);
int wPawn(PPC p);
int evalWking();
int evalBking();


#endif

end- pawn.h


pawn.c

Code: Select all
#include   "defs.h"         
#include   "pawns.h"         
#include   "wts.h"         
#include   "data.h"
#include   "eval.h"
#include   "geval.h"

int      max_pawn[2], p_score[2], ks_score[2];

//least advance pawn bitbase per file
_bb_t      ladvPRankG[2][8];   
_bb_t      ladvPRankGSide[2][8]; 

int      (*evalPawn[2])(PPC ) = {
   wPawn, bPawn
};

const   _bb_t      bbE[8] = {
   bbE0, bbE1,   bbE2,   bbE3,
   bbE4, bbE5,   bbE6,   bbE7   
};

// bits ahead in rank for color
const   _bb_t      rankG[2][8] = {
    bbL0,  bbL1,  bbL2,  bbL3,
    bbL4,  bbL5,  bbL6,  bbL7,
   
   bbG0,  bbG1,  bbG2,  bbG3,
   bbG4,  bbG5,  bbG6,  bbG7
};



int bPawn(PPC p){
   int isq = p->isq, r = iGetRank(isq), f = iGetFile(isq), v = 0;

   if (ladvPRankG[1][f]^rankG[1][r]){
      v -= DOUBLED_PAWN;
   }

   if (ladvPRankGSide[1][f]){
      //~ladvPRankGSide[1][f] == rankLE
      if (rankG[1][r]&~ladvPRankGSide[1][f]){
         v -= BACKWARD_PAWN;
      }
   }else{
      v -= LONE_PAWN;
      p->info |= INFO_PAWN_LONE;
   }

   if (!(bbE[r]&ladvPRankGSide[0][f]))//passed
   if (bbE[r]&ladvPRankG[0][f]){
      p->info |= INFO_PAWN_PASS;
      v += r * PASS_PAWN_PER_RANK;
   }else{
      p->info |= INFO_PAWN_PASS_X;   
      v += pst_p_pass_x[1][isq];
      if (max_pawn[1]){
         if (r >= iGetRank(max_pawn[1])){
            if (r > iGetRank(max_pawn[1])){
               max_pawn[1] = isq;
            }else{//check queening-sq when rank same, also consider lone (lesser priority)
               if (imaxRF(112+f, ksq[0])
                  > imaxRF(112+iGetFile(max_pawn[1]), ksq[0])){
                  max_pawn[1] = isq;
               }else if (brdPPC(max_pawn[1])->info&INFO_PAWN_LONE){
                  max_pawn[1] = isq;
               }
            }
         }
      }else {
         max_pawn[1] = isq;
      }
   }

   return v;
}


int wPawn(PPC p){
   int isq = p->isq, r = iGetRank(isq), f = iGetFile(isq), v = 0;

   if (ladvPRankG[0][f]^rankG[0][r]){
      v -= DOUBLED_PAWN;
   }

   if (ladvPRankGSide[0][f]){
      if (rankG[0][r]&~ladvPRankGSide[0][f]){
         v -= BACKWARD_PAWN;
      }
   }else{
      v -= LONE_PAWN;
      p->info |= INFO_PAWN_LONE;
   }


   if (!(bbE[r]&ladvPRankGSide[1][f]))//passed
   if (bbE[r]&ladvPRankG[1][f]){
      p->info |= INFO_PAWN_PASS;
      v += (7 - r) * PASS_PAWN_PER_RANK;
   }else{
      p->info  |= INFO_PAWN_PASS_X;
      v += pst_p_pass_x[0][isq];
      if (max_pawn[0]){
         if (r <= iGetRank(max_pawn[0])){
            if (r < iGetRank(max_pawn[0])){
               max_pawn[0] = isq;
            }else{//check queening -sq when rank same
               if (imaxRF(f, ksq[1]) > imaxRF(iGetFile(max_pawn[0]), ksq[1])){
                  max_pawn[0] = isq;
               }else if (brdPPC(max_pawn[0])->info&INFO_PAWN_LONE){
                  max_pawn[0] = isq;
               }
            }
         }
      }else{
         max_pawn[0] = isq;
      }
   }


   return v;
}

static int bkf(int f){//per file, for king in corner
   int v = 0;

   if (ladvPRankG[1][f]){//has pawn
      if (ladvPRankG[1][f]^rankG[1][1]){//file pawn moved
         if (ladvPRankG[1][f]^rankG[1][2]){
            v -= P_COVER_MOVED_2;// moved more than 1 sq
         }else{
            v -= P_COVER_MOVED_1;// moved 1 sq
         }
      }//else - file pawn not moved, ok
   }else{
      if (!ladvPRankG[0][f])// no oppn pawn, bad
      v -= P_COVER_ZERO+P_COVER_ZERO_XSIDE;
      else
      v -= P_COVER_ZERO;
   }

/*
      pawn storm
      =========
   1)oppn pawn moved passed horizontal center divide   
    2) pawn storm - only when kings not in  same side corner
    3) strictly should use most advanced pawns as may have doubled pawns;
      but a doubled has penalty;

  */

   if (ladvPRankG[0][f]
      //~ladvPRankG[1][f] == LE of least adv pawn
      //oppn pawn moved passed horizontal center divide   
      && bbE3&~ladvPRankG[0][f]//>= 5th rank
      && k_corner[0]^k_corner[1]){ //kings not same side corner
      if (bbE2&~ladvPRankG[0][f]){
         v -= PAWN_STORM_2;//6/7th rank
      }else{//5th rank
         v -= PAWN_STORM_1;
      }
   }

   return v;
}



static int wkf(int f){//for king in corner
   int v = 0;
   //std  10/15/24/15

   if (ladvPRankG[0][f]){//has pawn
      if (ladvPRankG[0][f]^rankG[0][6]){
         if (ladvPRankG[0][f]^rankG[0][5]){
            v -= P_COVER_MOVED_2;// moved more than 1 sq
         }else{
            v -= P_COVER_MOVED_1;// moved 1 sq
         }
      }//else - pawn not moved
   }else{
      if (!ladvPRankG[1][f])// no oppn pawn
      v -= P_COVER_ZERO+P_COVER_ZERO_XSIDE;
      else
      v -= P_COVER_ZERO;
   }
   
   //std  5 / 10
   if (ladvPRankG[1][f]//file has b pawn
      //~ladvPRankG[1][f] == LE of least adv pawn
      //oppn pawn moved passed horizontal center divide   
      && bbE4&~ladvPRankG[1][f]//>= 5th rank
      && k_corner[0]^k_corner[1]){ //kings not same side corner
      if (bbE5&~ladvPRankG[1][f]){
         v -= PAWN_STORM_2;//6/7th rank
      }else{//5th rank
         v -= PAWN_STORM_1;
      }
   }

   return v;
}

int evalBking()
{
   int v = 0;
   if (k_corner[1]){
      if (k_corner[1]&K_CORNER_A){
         v += bkf(0);
         v += bkf(1);
         v += bkf(2)/2;
      }else{
         v += bkf(7);
         v += bkf(6);
         v += bkf(5)/2;
      }
   }else{
      int i, f = iGetFile(ksq[1]);
      for (i = f-1; i <= f+1; ++i)
      if (!(ladvPRankG[0][i]|ladvPRankG[1][i]))//no pawns in file
      v -= P_COVER_CENTER_NULL;
   }

   //used in ksafety()
   ks_score[1] = v;
   assert(ks_score[1] <= 0 && ks_score[1] >= -127);
   
   return (v+PST_KING[1][ksq[1]])
               *(MAX_NP_MTL+nonpawn_mtl[0])*KS_SCORE_WT
                  /KS_SCORE_DIV /MAX_NP_MTLx2;
}



int evalWking()
{
   int v = 0;
//** max score < 40 x 2 + 20 + 30 = -130 ???
   if (k_corner[0]){
      if (k_corner[0]&K_CORNER_A){
         v += wkf(0);
         v += wkf(1);
         v += wkf(2)/2;
      }else{
         v += wkf(7);
         v += wkf(6);
         v += wkf(5)/2;
      }
   }else{
      int i, f = iGetFile(ksq[0]);
      for (i = f-1; i <= f+1; ++i)
      if (!(ladvPRankG[0][i]|ladvPRankG[1][i]))
      v -= P_COVER_CENTER_NULL;
   }

   //used in ksafety()
   ks_score[0] = v;
   assert(ks_score[0] <= 0 && ks_score[0] >= -127);
   
   return (v+PST_KING[0][ksq[0]])
               *(MAX_NP_MTL+nonpawn_mtl[1])*KS_SCORE_WT
                  /KS_SCORE_DIV /MAX_NP_MTLx2;
   // if least near endg, mtl factor is 0.45(r+q)
}



int eval(){


// initialize pawn arrays

   // 8 files need be reset
   *((U64 *)ladvPRankG[0]) = 0;
   *((U64 *)ladvPRankG[1]) = 0;
   *((U64 *)ladvPRankGSide[0]) = 0;
   *((U64 *)ladvPRankGSide[1]) = 0;
   
   for (i = 0; i <= 1; ++i)//2 colors
   for (j = 0; j < pawn_count[i]; ++j){//list thru pawns
      p = indPPC(i, j);
      ladvPRankG[i][ii = iGetFile(p->isq)] |=  rankG[i][iGetRank(p->isq)];
      if (ii>0){
         ladvPRankGSide[i][ii-1] |=  ladvPRankG[i][ii];
      }
      if (ii<7){
         ladvPRankGSide[i][ii+1] |=  ladvPRankG[i][ii];
      }
   }






}

eg code:-
int eval_knight_w(isq){


  if (!(bbE[iGetRank(isq)]&ladvPRankGSide[1][iGetFile(isq)])){//passed pawn
    score += N_PASSED_PAWN;
  }


}


Addition by moderator: Using the "Code" button makes source code a bit better readable IMO.

Regards

Volker

Re: Fuit's pawn evaluation using 8-bits ?

PostPosted: 09 Aug 2005, 09:16
by Fabien Letouzey
Chan Rasjid wrote:I have just figured out that probably fruit is using some sort of 8-bits bitboard (bitbase ?) to implement evaluation of pawn structure and pawns cover for king safety.I just finished emulating these same evaluation from TSCP using 8-bit char, 8 bits to represent rank/file 0-7 with 1,2,4,8,...


Yes, they are 8-bit bitboards. I call them "bitfiles".

Fabien.

PostPosted: 09 Aug 2005, 11:01
by Chan Rasjid
Yes, they are 8-bit bitboards. I call them "bitfiles".
Fabien.


Is it a surprise that Fruit is very much stronger than most other programs?

It is because Fabien uses 8-bit bitboards and not "8-bits bitboard" and
and uses the term "bitfiles". The file is not file as in "... a file in a C program" but as in "... the file ... in the chess board". The files of the chess board are represented using 8 bits and therefore "bitfiles".

One who is good in language syntax is likely to be good in C syntax.

Or is it syntac?.

Rasjid