/*
Protector -- a UCI chess engine
Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _position_h_
#define _position_h_
#include "protector.h"
#include "bitboard.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#define MAX_DEPTH 64
#define POSITION_HISTORY_OFFSET 100
#define MAX_GAIN 512
#define MAX_GAIN_MOVESORT 127
#define DEFAULT_HASHTABLE_EXPONENT 16
#define SEARCHEVENT_SEARCH_FINISHED 1
#define SEARCHEVENT_PLY_FINISHED 2
#define SEARCHEVENT_NEW_PV 3
#define SEARCHEVENT_NEW_BASEMOVE 4
#define SEARCHEVENT_STATISTICS_UPDATE 5
#define PAWN_DEFAULTVALUE_OPENING (88) /* was 75 */
#define PAWN_DEFAULTVALUE_ENDGAME (112) /* was 100 */
#define OP_UNIT PAWN_DEFAULTVALUE_OPENING
#define EG_UNIT PAWN_DEFAULTVALUE_ENDGAME
#define PHASE_MAX 62
#define PHASE_INDEX_MAX 256
#define PIECEWEIGHT_ENDGAME 18
#ifdef TEST_SETUP
#define DEFAULTVALUE_KNIGHT_OPENING ((400*OP_UNIT) / 100) /* R3: 331; SF: 413 */
#define DEFAULTVALUE_KNIGHT_ENDGAME ((335*EG_UNIT) / 100) /* R3: 284; SF: 328 */
#define DEFAULTVALUE_BISHOP_OPENING ((405*OP_UNIT) / 100) /* R3: 350; SF: 422 */
#define DEFAULTVALUE_BISHOP_ENDGAME ((325*EG_UNIT) / 100) /* R3: 288; SF: 332 */
#define DEFAULTVALUE_ROOK_OPENING ((640*OP_UNIT) / 100) /* R3: 506; SF: 641 */
#define DEFAULTVALUE_ROOK_ENDGAME ((500*EG_UNIT) / 100) /* R3: 488; SF: 495 */
#define DEFAULTVALUE_QUEEN_OPENING ((1240*OP_UNIT) / 100) /* R3: 1000; SF: 1273 */
#define DEFAULTVALUE_QUEEN_ENDGAME ((990*EG_UNIT) / 100) /* R3: 920; SF: 991 */
#define DEFAULTVALUE_BISHOP_PAIR_OPENING ((50*OP_UNIT) / 100) /* R3: 44 */
#define DEFAULTVALUE_BISHOP_PAIR_ENDGAME ((60*EG_UNIT) / 100) /* R3: 44 */
#define DEFAULTVALUE_PIECE_UP_OPENING 40
#define DEFAULTVALUE_PIECE_UP_ENDGAME 20
#else
#define DEFAULTVALUE_KNIGHT_OPENING ((410*OP_UNIT) / 100) /* R3: 331; SF: 413 */
#define DEFAULTVALUE_KNIGHT_ENDGAME ((325*EG_UNIT) / 100) /* R3: 284; SF: 328 */
#define DEFAULTVALUE_BISHOP_OPENING ((395*OP_UNIT) / 100) /* R3: 350; SF: 422 */
#define DEFAULTVALUE_BISHOP_ENDGAME ((325*EG_UNIT) / 100) /* R3: 288; SF: 332 */
#define DEFAULTVALUE_ROOK_OPENING ((590*OP_UNIT) / 100) /* R3: 506; SF: 641 */
#define DEFAULTVALUE_ROOK_ENDGAME ((500*EG_UNIT) / 100) /* R3: 488; SF: 495 */
#define DEFAULTVALUE_QUEEN_OPENING ((1240*OP_UNIT) / 100) /* R3: 1000; SF: 1273 */
#define DEFAULTVALUE_QUEEN_ENDGAME ((1000*EG_UNIT) / 100) /* R3: 920; SF: 991 */
#define DEFAULTVALUE_BISHOP_PAIR_OPENING ((60*OP_UNIT) / 100) /* R3: 44 */
#define DEFAULTVALUE_BISHOP_PAIR_ENDGAME ((60*EG_UNIT) / 100) /* R3: 44 */
#endif
#define DEFAULT_THREAT_LIMIT 20
extern int VALUE_QUEEN_OPENING;
extern int VALUE_QUEEN_ENDGAME;
extern int VALUE_ROOK_OPENING;
extern int VALUE_ROOK_ENDGAME;
extern int VALUE_BISHOP_OPENING;
extern int VALUE_BISHOP_ENDGAME;
extern int VALUE_KNIGHT_OPENING;
extern int VALUE_KNIGHT_ENDGAME;
extern int PAWN_VALUE_OPENING;
extern int PAWN_VALUE_ENDGAME;
extern int VALUE_BISHOP_PAIR_OPENING;
extern int VALUE_BISHOP_PAIR_ENDGAME;
#define OPENING 0
#define ENDGAME 1
extern int basicValue[16], simplePieceValue[16];
extern INT32 pieceSquareBonus[16][_64_];
extern int pieceCountShift[16];
extern int krqIndexWhite[4096], bbpIndexWhite[4096];
extern int krqIndexBlack[4096], bbpIndexBlack[4096];
typedef struct
{
Piece piece[_64_];
Color activeColor;
BYTE castlingRights;
Square enPassantSquare;
int moveNumber, halfMoveClock;
/**
* Redundant data
*/
Bitboard allPieces;
Bitboard piecesOfColor[2];
Bitboard piecesOfType[16];
Square king[2];
int numberOfPieces[2];
int numberOfPawns[2];
UINT64 pieceCount;
INT32 balance;
UINT64 hashValue, pawnHashValue;
}
Position;
typedef UINT32 Move;
typedef struct
{
Square square;
Bitboard moves;
}
MovesOfPiece;
typedef struct
{
Bitboard diaAttackers, orthoAttackers, knightAttackers, pawnAttackers[2];
Square attackedByDia[_64_], attackedByOrtho[_64_];
}
KingAttacks;
typedef struct
{
Move killerMove1, killerMove2, killerMove3, killerMove4;
Move currentMove;
int indexCurrentMove;
bool currentMoveIsCheck;
Piece captured, restorePiece1, restorePiece2;
Square enPassantSquare, restoreSquare1, restoreSquare2, kingSquare;
BYTE castlingRights;
int halfMoveClock;
Bitboard allPieces, whitePieces, blackPieces, hashValue, pawnHashValue;
INT32 balance;
int staticValue, refinedStaticValue, futilityMargin;
bool staticValueAvailable, gainsUpdated;
bool quietMove;
UINT64 pieceCount;
bool hangingPieces;
}
PlyInfo;
typedef struct
{
Position *position;
PlyInfo *plyInfo;
Move hashMove;
Move moves[MAX_MOVES_PER_POSITION];
Move badCaptures[MAX_MOVES_PER_POSITION];
bool killer1Executed, killer2Executed, killer3Executed, killer4Executed;
MovesOfPiece movesOfPiece[16];
int numberOfMoves, numberOfBadCaptures;
int nextMove, currentStage, numberOfPieces;
UINT16 *historyValue;
INT16 *positionalGain;
}
Movelist;
#define HASHVALUE_UPPER_LIMIT 0
#define HASHVALUE_EXACT 1
#define HASHVALUE_LOWER_LIMIT 2
#define HASHVALUE_EVAL 3
#define HASHFLAG_PIECES_HANGING 4
typedef struct
{
UINT64 key;
UINT64 data;
UINT32 staticValueData;
}
Hashentry;
typedef struct
{
Hashentry *table;
unsigned long tableSize, entriesUsed;
UINT64 hashMask;
int exponent;
UINT8 date;
}
Hashtable;
typedef enum
{
SEARCH_STATUS_RUNNING,
SEARCH_STATUS_TERMINATE,
SEARCH_STATUS_ABORT,
SEARCH_STATUS_FINISHED
}
SearchStatus;
#define HISTORY_SIZE (12*64*64)
#ifdef VALUE_BASED_MOVESORT
#define HISTORY_MAX 127
#else
#define HISTORY_MAX 16384
#endif
#define HISTORY_LIMIT 60 /* (60%) */
typedef struct
{
UINT16 move[MAX_DEPTH + 2];
int length, score;
}
PrincipalVariation;
typedef struct
{
Bitboard hashValue;
Bitboard pawnProtectedSquares[2];
Bitboard passedPawns[2];
Bitboard pawnAttackableSquares[2];
bool hasPassersOrCandidates[2];
INT32 balance;
int pawnLightSquareMalus[2], pawnDarkSquareMalus[2];
}
PawnHashInfo;
typedef struct
{
Bitboard hashValue;
int safetyMalus;
}
KingSafetyHashInfo;
#define BONUS_HIDDEN_PASSER
typedef enum
{
Se_None,
Se_KpK,
Se_KnnKp,
Se_KbpK,
Se_KrpKb,
Se_KrpKr,
Se_KrppKr,
Se_KqpKq,
Se_KqppKq
} SpecialEvalType;
typedef struct
{
UINT8 chancesWhite, chancesBlack;
SpecialEvalType specialEvalWhite, specialEvalBlack;
INT32 materialBalance;
int phaseIndex;
}
MaterialInfo;
typedef struct
{
Bitboard upwardRealm[2];
Bitboard downwardRealm[2];
Bitboard pawnAttackableSquares[2];
Bitboard pawnProtectedSquares[2];
Bitboard doubledPawns[2];
Bitboard passedPawns[2];
Bitboard candidatePawns[2];
#ifdef BONUS_HIDDEN_PASSER
Bitboard hiddenCandidatePawns[2];
bool hasPassersOrCandidates[2];
#endif
#ifdef MALUS_SLIGHTLY_BACKWARD
Bitboard slightlyBackward[2];
#endif
Bitboard weakPawns[2];
Bitboard fixedPawns[2];
Bitboard countedSquares[2];
Bitboard unprotectedPieces[2];
Bitboard kingAttackSquares[2];
Bitboard attackedSquares[2];
Bitboard batteryAttackers[2];
Bitboard knightAttackedSquares[2];
Bitboard bishopAttackedSquares[2];
Bitboard rookAttackedSquares[2];
Bitboard rookSupportedSquares[2];
Bitboard queenAttackedSquares[2];
Bitboard queenSupportedSquares[2];
Bitboard chainPawns[2];
INT32 attackInfo[2];
int kingSquaresAttackCount[2];
Bitboard hangingPieces[2];
int spaceAttackPoints[2];
int pawnLightSquareMalus[2];
int pawnDarkSquareMalus[2];
bool evaluateKingSafety[2];
KingSafetyHashInfo *kingsafetyHashtable;
INT32 balance, materialBalance;
int futilityMargin[2];
MaterialInfo *materialInfo;
}
EvaluationBase;
#define PAWN_HASHTABLE_MASK 0xffff
#define PAWN_HASHTABLE_SIZE ((PAWN_HASHTABLE_MASK)+0x0001)
#define KINGSAFETY_HASHTABLE_MASK 0x07ffff
#define KINGSAFETY_HASHTABLE_SIZE ((KINGSAFETY_HASHTABLE_MASK)+0x0001)
typedef struct
{
int ply, nominalDepth, selDepth;
int numberOfBaseMoves, numberOfCurrentBaseMove;
Move currentBaseMove, bestBaseMove;
Position singlePosition, startPosition;
PlyInfo plyInfo[MAX_DEPTH + 2];
PrincipalVariation pv;
Hashtable *hashtable;
PawnHashInfo *pawnHashtable;
KingSafetyHashInfo *kingsafetyHashtable;
UINT64 positionHistory[POSITION_HISTORY_OFFSET + MAX_DEPTH + 2];
UINT64 nodes;
UINT16 *historyValue;
UINT16 *historyTotalCount;
UINT16 *historyHitCount;
INT16 *positionalGain;
long startTime, timeTarget, timeLimit, finishTime, timestamp;
long startTimeProcess, finishTimeProcess;
unsigned long tbHits;
void (*handleSearchEvent) (int, void *);
SearchStatus searchStatus;
int drawScore[2];
bool easyMove, bestMoveChange;
bool terminate, ponderMode, terminatePondering, failingHighOrLow;
int previousBest, expectedScore;
long numPvUpdates;
unsigned int threadNumber;
}
Variation;
#define V(op,eg) ( (op) + ( (eg) << 16 ) )
#define HV(op,eg) ( (((op)*100)/256) + ( (((eg)*100)/256) << 16 ) )
/**
* Flip the specified position.
*/
void flipPosition(Position * position);
/**
* Remove all pieces from the specified position.
*/
void clearPosition(Position * position);
/**
* Calculate the redundant data of the specified position.
*/
void initializePosition(Position * position);
/**
* Prepare a search with the specified variation.
*/
void prepareSearch(Variation * variation);
/**
* Reset history values.
*/
void resetHistoryValues(Variation * variation);
/**
* Reset history hit values.
*/
void resetHistoryHitValues(Variation * variation);
/**
* Reset gain values.
*/
void resetGainValues(Variation * variation);
/**
* Shrink all history values.
*/
void shrinkHistoryValues(Variation * variation);
/**
* Shrink all history hit values.
*/
void shrinkHistoryHitValues(Variation * variation);
/**
* Initialize a variation with the position specified by 'fen'.
* Prepare a search.
*/
void initializeVariation(Variation * variation, const char *fen);
/**
* Initialize a variation with the position specified by 'position'.
* To perform a search, call 'prepareSearch' afterwards.
*/
void setBasePosition(Variation * variation, const Position * position);
/**
* Set the value of a definite draw.
*/
void setDrawScore(Variation * variation, int score, Color color);
/**
* Get the pieces interested in moving to 'square'.
*/
Bitboard getInterestedPieces(const Position * position, const Square square,
const Color attackerColor);
/**
* Make the specified move at the current end of the specified variation.
*
* @return 1 if the move was an illegal castling move, 0 otherwise
*/
int makeMove(Variation * variation, const Move move);
/**
* Make the specified move at the current end of the specified variation.
*
* @return 1 if the move was an illegal castling move, 0 otherwise
*/
int makeMoveFast(Variation * variation, const Move move);
/**
* Unmake the last move.
*/
void unmakeLastMove(Variation * variation);
/**
* Test if a move attacks the opponent's king.
*
* @return FALSE if the specified move doesn't attack
* the opponent's king, TRUE otherwise
*/
bool moveIsCheck(const Move move, const Position * position);
/**
* Check if the specified position is consistent.
*
* @return 0 if the specified position is consistent
*/
int checkConsistency(const Position * position);
/**
* Check if the specified variation is consistent.
*
* @return 0 if the specified variation is consistent
*/
int checkVariation(Variation * variation);
/**
* Check if the given position is legal.
*/
bool positionIsLegal(const Position * position);
/**
* Check if the specified position are identical (excluding move numbers).
*/
bool positionsAreIdentical(const Position * position1,
const Position * position2);
/**
* Calculate the signature for a given set of piece counters.
*/
UINT32 materialSignature(const UINT32 numQueens, const UINT32 numRooks,
const UINT32 numLightSquareBishops,
const UINT32 numDarkSquareBishops,
const UINT32 numKnights, const UINT32 numPawns);
INLINE Square relativeSquare(const Square square, const Color color);
INLINE INT32 evalBonus(INT32 openingBonus, INT32 endgameBonus);
INLINE int getOpeningValue(INT32 value);
INLINE int getEndgameValue(INT32 value);
INLINE void addBonusForColor(const INT32 bonus, Position * position,
const Color color);
INLINE UINT16 packedMove(const Move move);
INLINE Move getMove(const Square from, const Square to,
const Piece newPiece, const INT16 value);
INLINE Move getOrdinaryMove(const Square from, const Square to);
INLINE Move getPackedMove(const Square from, const Square to,
const Piece newPiece);
INLINE Square getFromSquare(const Move move);
INLINE Square getToSquare(const Move move);
INLINE Piece getNewPiece(const Move move);
INLINE INT16 getMoveValue(const Move move);
INLINE void setMoveValue(Move * move, const int value);
INLINE Color opponent(Color color);
INLINE Bitboard getDirectAttackers(const Position * position,
const Square square,
const Color attackerColor,
const Bitboard obstacles);
INLINE Bitboard getDiaSquaresBehind(const Position * position,
const Square targetSquare,
const Square viewPoint);
INLINE Bitboard getOrthoSquaresBehind(const Position * position,
const Square targetSquare,
const Square viewPoint);
INLINE void initializePlyInfo(Variation * variation);
INLINE int numberOfNonPawnPieces(const Position * position,
const Color color);
INLINE bool hasOrthoPieces(const Position * position, const Color color);
INLINE bool hasQueen(const Position * position, const Color color);
INLINE void appendMoveToPv(const PrincipalVariation * oldPv,
PrincipalVariation * newPv, const Move move);
INLINE INT16 calcHashtableValue(const int value, const int ply);
INLINE int calcEffectiveValue(const int value, const int ply);
INLINE Bitboard getOrdinaryPieces(const Position * position,
const Color color);
INLINE Bitboard getNonPawnPieces(const Position * position,
const Color color);
INLINE Bitboard getOrthoPieces(const Position * position, const Color color);
INLINE bool movesAreEqual(const Move m1, const Move m2);
INLINE int getPieceCount(const Position * position, const Piece piece);
INLINE bool pieceIsPresent(const Position * position, const Piece piece);
INLINE int historyIndex(const Move move, const Position * position);
INLINE int moveIndex(const Move move, const Position * position);
INLINE int moveGainIndex(const Move move, const Position * position);
INLINE int getMinimalDistance(const Position * position,
const Square origin, const Piece piece);
INLINE int getMinimalTaxiDistance(const Position * position,
const Square origin, const Piece piece);
INLINE int getPieceWeight(const Position * position, const Color color);
INLINE int phaseIndex(const Position * position);
INLINE void getPieceCounters(UINT32 materialSignature,
int *numWhiteQueens, int *numWhiteRooks,
int *numWhiteLightSquareBishops,
int *numWhiteDarkSquareBishops,
int *numWhiteKnights, int *numWhitePawns,
int *numBlackQueens, int *numBlackRooks,
int *numBlackLightSquareBishops,
int *numBlackDarkSquareBishops,
int *numBlackKnights, int *numBlackPawns);
INLINE UINT32 calculateMaterialSignature(const Position * position);
#ifdef INLINE_IN_HEADERS
#include "positionInline.h"
#endif
/**
* Initialize this module.
*
* @return 0 if no errors occurred.
*/
int initializeModulePosition(void);
/**
* Test this module.
*
* @return 0 if all tests succeed.
*/
int testModulePosition(void);
#endif