home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
- //----------------------------------------------------------------------------
- #include <owl/pch.h>
- #include <owl/defs.h>
- #include <math.h>
- #include "wcdefs.h"
- #include "externs.h"
-
- MAXTYPE RootValue;
- BOARDTYPE Board[0x78];
-
- #undef max
- #undef min
- #define max(a, b) (((a) > (b)) ? (a) : (b))
- #define min(a, b) (((a) < (b)) ? (a) : (b))
-
- #define TOLERANCE 8 // Tolerance width
- #define EXCHANGEVALUE 32
- // Value for exchanging pieces when ahead (not pawns)
- #define ISOLATEDPAWN 20
- // Isolated pawn. Double isolated pawn is 3 * 20
- #define DOUBLEPAWN 8 // Double pawn
- #define SIDEPAWN 6 // Having a pawn on the side
- #define CHAINPAWN 3 // Being covered by a pawn
- #define COVERPAWN 3 // covering a pawn
- #define NOTMOVEPAWN 2 // Penalty for moving pawn
- #define BISHOPBLOCKVALUE 20
- // Penalty for bishop blocking d2/e2 pawn
- #define ROOKBEHINDPASSPAWN 16 // Bonus for Rook behind passed pawn
-
-
- typedef unsigned char FILETYPE; // file numbers
- typedef unsigned char RANKTYPE; // rank numbers
- typedef unsigned char SETOFFILE;
- typedef struct {
- SETOFFILE one, dob;
- } PAWNBITTYPE[2];
-
- //
- // Global variables for this module
- //
- int PieceValue[7] = {0, 0x1000, 0x900, 0x4c0, 0x300, 0x300, 0x100};
- const char distan[8] = { 3, 2, 1, 0, 0, 1, 2, 3 };
- // The value of a pawn is the sum of Rank and file values.
- // The file value is equal to PawnFileFactor * (Rank Number + 2)
- const char pawnrank[8] = {0, 0, 0, 2, 4, 8, 30, 0};
- const char passpawnrank[8] = {0, 0, 10, 20, 40, 60, 70, 0};
- const char pawnfilefactor[8] = {0, 0, 2, 5, 6, 2, 0, 0};
- const char castvalue[2] = {4, 32}; // Value of castling
-
- const SETOFFILE filebittab[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
- PAWNBITTYPE pawnbitt[MAXPLY + 2];
- PAWNBITTYPE *pawnbit = &pawnbitt[1];
- int totalmaterial, pawntotalmaterial, material;
- // Material level of the game
- // (early middlegame = 43 - 32, endgame = 0)
- int materiallevel;
- const unsigned char squarerankvalue[8] = { 0, 0, 0, 0, 1, 2, 4, 4};
- COLORTYPE tempcolor;
- int temp, temp2; // temporary junk
-
-
- //
- // count the number of set bits in b
- //
- static int
- count(SETOFFILE b)
- {
- char cnt = 0;
- while (b) {
- if (b % 2 == 1)
- cnt++;
- b >>= 1;
- }
- return cnt;
- }
-
- //
- // Calculate value of the pawn structure in pawnbit[depth][color]
- //
- static int
- pawnstrval(DEPTHTYPE depth, COLORTYPE color)
- {
- SETOFFILE iso; // contains FILEs with isolated pawns
-
- iso = SETOFFILE(pawnbit[depth][color].one &
- ~((pawnbit[depth][color].one << 1) | (pawnbit[depth][color].one >> 1)));
- return -(count(pawnbit[depth][color].dob) * DOUBLEPAWN +
- count(iso) * ISOLATEDPAWN + count(iso &
- pawnbit[depth][color].dob) * ISOLATEDPAWN * 2);
- }
-
- //
- // calculate the value of the piece on the square
- //
- inline int
- PiecePosVal(PIECETYPE piece, COLORTYPE color, SQUARETYPE square)
- {
- return PieceValue[piece] + PVTable[color][piece][square];
- }
-
-
- short mating; // mating evaluation function is used
-
- //
- // calculates piece-value table for the static evaluation function
- //
- void
- CalcPVTable()
- {
- typedef SETOFFILE PAWNTABTYPE[8];
-
- PAWNTABTYPE pawntab[2];
- // Bit tables for static pawn structure evaluation
- SETOFFILE pawnfiletab, bit, oppasstab, behindoppass,
- leftsidetab, rightsidetab, sidetab, leftchaintab,
- rightchaintab, chaintab, leftcovertab, rightcovertab;
-
- // Importance of an attack of the square
- char attackvalue[2][0x78];
- // Value of squares controlled from the square
- int pvcontrol[2][5][0x78];
-
- COLORTYPE losingcolor; // the color which is being mated
- int posval; // The positional value of piece
- int attval; // The attack value of the square
- FILETYPE line; // The file of the piece
- RANKTYPE rank; // The rank of the piece
- char dist, kingdist; // Distance to center, to opponents king
- CASTTYPE cast; // Possible castlings
- short direct; // Indicates direct attack
- int cnt; // Counter for attack values
- int strval; // Pawnstructure value
- COLORTYPE color, oppcolor; // Color and opponents color
- PIECETYPE piececount; // Piece counter
- SQUARETYPE square; // Square counter
- DIRTYPE dir; // Direction counter
- EDGESQUARETYPE sq; // Square counter
- int temp, temp2; // temporary junk
-
- // Calculate SAMMAT, PAWNSAMMAT and Material
- material = pawntotalmaterial = totalmaterial = mating = 0;
-
- for (square = 0; square < 0x78; square++)
- if (!(square & 0x88))
- if (Board[square].piece != empty)
- if (Board[square].piece != king) {
- temp = PieceValue[Board[square].piece];
- totalmaterial += temp;
- if (Board[square].piece == pawn)
- pawntotalmaterial += PieceValue[pawn];
- if (Board[square].color == white)
- temp = -temp;
- material -= temp;
- }
- materiallevel = max(0, totalmaterial - 0x2000) / 0x100;
- // Set mating if weakest player has less than the equivalence
- // of two bishops and the advantage is at least a rook for a bishop
- if (material < 0)
- losingcolor = white;
- else
- losingcolor = black;
- mating = ((totalmaterial - abs(material)) / 2 <= PieceValue[bishop] * 2)
- && (abs(material) >= PieceValue[rook] - PieceValue[bishop]);
- // Calculate ATTACKVAL (importance of each square)
- for (rank = 0; rank < 8; rank++)
- for (line = 0; line < 8; line++) {
- square = (rank << 4) + line;
- attval = max(0, 8 - 3 * (distan[rank] + distan[line]));
- // center importance
- // Rank importrance
- for (color = white; color <= black; ((int)color)++) {
- attackvalue[color][square] = char(((squarerankvalue[rank] * 3 *
- (materiallevel + 8)) >> 5) + attval);
- square ^= 0x70;
- }
- }
- for (color = white; color <= black; ((int)color)++) {
- oppcolor = (COLORTYPE)(1 - color);
- CalcCastling(oppcolor, &cast);
- if (cast != shrt && materiallevel > 0)
- // Importance of the 8 squares around the opponent's King
- for (dir = 0; dir < 8; dir++) {
- sq = PieceTab[oppcolor][0].isquare + DirTab[dir];
- if (!(sq & 0x88))
- attackvalue[color][sq] += char(((12 * (materiallevel + 8)) >> 5));
- }
- }
-
- // Calculate PVControl
- for (square = 0x77; square >=0; square--)
- if(!(square & 0x88))
- for (color = white; color <= black; ((int)color)++)
- for (piececount = rook; piececount <= bishop; ((int)piececount)++)
- pvcontrol[color][piececount][square] = 0;
- for (square = 0x77; square >=0; square--)
- if (!(square & 0x88))
- for (color = white; color <= black; ((int)color)++) {
- for (dir = 7; dir >= 0; dir--) {
- if (dir < 4)
- piececount = rook;
- else
- piececount = bishop;
- // Count value of all attacs from the square in
- // the Direction.
- // The Value of attacking a Square is Found in ATTACKVAL.
- // Indirect Attacks (e.g. a Rook attacking through
- // another Rook) counts for a Normal attack,
- // Attacks through another Piece counts half
- cnt = 0;
- sq = square;
- direct = 1;
- do {
- sq += DirTab[dir];
- if (sq & 0x88)
- goto TEN;
- temp = attackvalue[color][sq];
- if (direct)
- cnt += temp;
- else
- cnt += (temp >> 1);
- if (Board[sq].piece != empty)
- if (Board[sq].piece != piececount && Board[sq].piece != queen)
- direct = 0;
- } while (Board[sq].piece != pawn);
- TEN: pvcontrol[color][piececount][square] += (cnt >> 2);
- }
- }
-
- // Calculate PVTable, value by value
- for (square = 0x77; square >= 0; square--)
- if (!(square & 0x88)) {
- for (color = white; color <= black; ((int)color)++) {
- oppcolor = (COLORTYPE)(1 - color);
- line = FILETYPE(square & 7);
- rank = RANKTYPE(square >> 4);
- if (color == black)
- rank = RANKTYPE(7 - rank);
- dist = char(distan[rank] + distan[line]);
- kingdist = char(abs((square >> 4) - (PieceTab[oppcolor][0].isquare >> 4)) +
- ((square - PieceTab[oppcolor][0].isquare) & 7));
- for (piececount = king; piececount <= pawn; ((int)piececount)++) {
- posval = 0; // Calculate POSITIONAL Value for
- // The piece on the Square
- if (mating && piececount != pawn) {
- if (piececount == king)
- if (color == losingcolor) { // Mating evaluation
- posval = 128 - 16 * distan[rank] - 12 * distan[line];
- if (distan[rank] == 3)
- posval -= 16;
-
- } else {
- posval = 128 - 4 * kingdist;
- if (distan[rank] >= 2 || distan[line] == 3)
- posval -= 16;
- }
- } else {
- temp = pvcontrol[color][rook][square];
- temp2 = pvcontrol[color][bishop][square];
- // Normal evaluation function
- switch (piececount) {
- case king:
- if (materiallevel <= 0)
- posval = -2 * dist;
- break;
- case queen:
- posval = (temp + temp2) >> 2;
- break;
- case rook:
- posval = temp;
- break;
- case bishop:
- posval = temp2;
- break;
- case knight:
- cnt = 0;
- for (dir = 0; dir < 8; dir++) {
- sq = square + KnightDir[dir];
- if (!(sq & 0x88))
- cnt += attackvalue[color][sq];
- }
- posval = (cnt >> 1) - dist * 3;
- break;
- case pawn :
- if (rank != 0 && rank != 7)
- posval = pawnrank[rank] + pawnfilefactor[line] * (rank+2) - 12;
- }
- }
- PVTable[color][piececount][square] = posval;
- }
- }
- }
-
- // Calculate pawntab (indicates which squares contain pawns)
-
- for (color = white; color <= black; ((int)color)++)
- for (rank = 0; rank < 8; rank++)
- pawntab[color][rank] = 0;
- for (square = 0x77; square >= 0; square--)
- if (!(square & 0x88))
- if (Board[square].piece == pawn) {
- rank = RANKTYPE(square >> 4);
- if (Board[square].color == black)
- rank = RANKTYPE(7 - rank);
- pawntab[Board[square].color][rank] |= filebittab[square & 7];
- }
- for (color = white; color <= black; ((int)color)++) { // initialize pawnbit
- pawnbit[-1][color].one = pawnbit[-1][color].dob = 0;
- for (rank = 1; rank < 7; rank++) {
- temp = pawntab[color][rank];
- pawnbit[-1][color].dob |= SETOFFILE((pawnbit[-1][color].one & temp));
- pawnbit[-1][color].one |= SETOFFILE(temp);
- }
- }
-
- // Calculate pawnstructurevalue
- RootValue = pawnstrval(-1, Player) - pawnstrval(-1, Opponent);
-
- // Calculate static value for pawn structure
- for (color = white; color <= black; ((int)color)++) {
- oppcolor = (COLORTYPE)(1 - color);
- pawnfiletab = leftsidetab = rightsidetab = behindoppass = 0;
- oppasstab = 0xff;
- for (rank = 1; rank < 7; rank++) {
- // Squares where opponents pawns are passed pawns
- oppasstab &= SETOFFILE((~(pawnfiletab | leftsidetab | rightsidetab)));
- // Squares behind the opponents passed pawns
- behindoppass |= (oppasstab & pawntab[oppcolor][7 - rank]);
- // squares which are covered by a pawn
- leftchaintab = leftsidetab;
- rightchaintab = rightsidetab;
- pawnfiletab = pawntab[color][rank]; // squares w/ pawns
- // squares w/ a pawn beside them
- leftsidetab = SETOFFILE((pawnfiletab << 1) & 0xff);
- rightsidetab = SETOFFILE((pawnfiletab >> 1) & 0xff);
- sidetab = leftsidetab | rightsidetab;
- chaintab = leftchaintab | rightchaintab;
- // squares covering a pawn
- temp = pawntab[color][rank+1];
- leftcovertab = SETOFFILE((temp << 1) & 0xff);
- rightcovertab = SETOFFILE((temp >> 1 ) & 0xff);
- sq = rank << 4;
- if (color == black)
- sq ^= 0x70;
- bit = 1;
- while (bit) {
- strval = 0;
- if (bit & sidetab)
- strval = SIDEPAWN;
- else if (bit & chaintab)
- strval = CHAINPAWN;
- if (bit & leftcovertab)
- strval += COVERPAWN;
- if (bit & rightcovertab)
- strval += COVERPAWN;
- if (bit & pawnfiletab)
- strval += NOTMOVEPAWN;
- PVTable[color][pawn][sq] += strval;
- if ((materiallevel <= 0) || (oppcolor != ProgramColor))
- {
- if (bit & oppasstab)
- PVTable[oppcolor][pawn][sq] += passpawnrank[7 - rank];
- if (bit & behindoppass)
- {
- temp = sq ^ 0x10;
- for (tempcolor = black; tempcolor >= white
- ; ((int)tempcolor)--)
- {
- PVTable[tempcolor][rook][sq] +=
- ROOKBEHINDPASSPAWN;
- if (rank == 6)
- PVTable[tempcolor][rook][temp] +=
- ROOKBEHINDPASSPAWN;
- }
- }
- }
- sq++;
- bit = SETOFFILE((bit << 1) & 0xff);
- }
- }
- }
-
- // Calculate penalty for blocking center pawns with a bishop
- for (sq = 3; sq < 5; sq ++) {
- if (Board[sq + 0x10].piece == pawn && Board[sq + 0x10].color == white)
- PVTable[white][bishop][sq + 0x20] -= BISHOPBLOCKVALUE;
- if (Board[sq+0x60].piece == pawn && Board[sq+0x60].color == black)
- PVTable[black][bishop][sq+0x50] -= BISHOPBLOCKVALUE;
- }
- for (square = 0x77; square >= 0; square--) // Calculate RootValue
- if (!(square & 0x88))
- if (Board[square].piece != empty)
- if (Board[square].color == Player)
- RootValue += PiecePosVal(Board[square].piece, Player, square);
- else
- RootValue -= PiecePosVal(Board[square].piece, Opponent, square);
- }
-
- //----------------------------------------------------------------------------
-
- int value;
- SQUARETYPE castsquare, cornersquare, epsquare;
-
- //
- // Update pawnbit and calculates value when a pawn is removed from line
- //
- inline int
- decpawnstrval(COLORTYPE color, FILETYPE line)
- {
- temp = ~filebittab[line];
- pawnbit[Depth][color].one = SETOFFILE((pawnbit[Depth][color].one & temp) |
- pawnbit[Depth][color].dob);
- pawnbit[Depth][color].dob &= SETOFFILE(temp);
- return int(pawnstrval(Depth, color) - pawnstrval(DEPTHTYPE(Depth - 1), color));
- }
-
- //
- // Update pawnbit and calculates value when a pawn moves
- // from old to new1 file
- //
- static int
- movepawnstrval(COLORTYPE color, FILETYPE new1, FILETYPE old)
- {
- temp = filebittab[new1];
- temp2 = ~filebittab[old];
- pawnbit[Depth][color].dob |= SETOFFILE((pawnbit[Depth][color].one & temp));
- pawnbit[Depth][color].one = SETOFFILE((pawnbit[Depth][color].one & temp2) |
- pawnbit[Depth][color].dob | temp);
- pawnbit[Depth][color].dob &= SETOFFILE(temp2);
- return int(pawnstrval(Depth, color) - pawnstrval(DEPTHTYPE(Depth - 1), color));
- }
-
- //----------------------------------------------------------------------------
-
- //
- // Calculate STATIC evaluation of the move
- //
- int
- StatEvalu(MOVETYPE *move)
- {
- value = 0;
- if (move->spe)
- if (move->movpiece == king) {
- GenCastSquare(move->new1, &castsquare, &cornersquare);
- value = PiecePosVal(rook, Player, castsquare) -
- PiecePosVal(rook,Player, cornersquare);
- if (move->new1 > move->old)
- value += castvalue[shrt-1];
- else
- value += castvalue[lng-1];
-
- } else if (move->movpiece == pawn) {
- epsquare = move->new1 - PawnDir[Player]; // E.p. capture
- value = PiecePosVal(pawn, Opponent, epsquare);
-
- } else // Pawnpromotion
- value = PiecePosVal(move->movpiece, Player, move->old) -
- PiecePosVal(pawn, Player, move->old) +
- decpawnstrval(Player, FILETYPE(move->old & 7));
-
- if (move->content != empty) { // normal moves
- value += PiecePosVal(move->content, Opponent, move->new1);
- // Penalty for exchanging pieces when behind in material
- if (abs(MainEvalu) >= 0x100)
- if (move->content != pawn)
- if ((ProgramColor == Opponent) == (MainEvalu >= 0))
- value -= EXCHANGEVALUE;
- }
- pawnbit[Depth][black] = pawnbit[Depth - 1][black]; // calculate pawnbit
- pawnbit[Depth][white] = pawnbit[Depth - 1][white];
- if (move->movpiece == pawn && (move->content != empty || move->spe))
- value += movepawnstrval(Player, FILETYPE(move->new1 & 7), FILETYPE(move->old & 7));
- if (move->content == pawn || move->spe && move->movpiece == pawn)
- value -= decpawnstrval(Opponent, FILETYPE(move->new1 & 7));
- // Calculate value of move
- return value + PiecePosVal(move->movpiece, Player, move->new1) -
- PiecePosVal(move->movpiece, Player, move->old);
- }
-