/*
 
 *******************************************************************************
 
 *                                                                             *
 
 *   configuration information:  the following variables need to be set to     *
 
 *   indicate the machine configuration/capabilities.                          *
 
 *                                                                             *
 
 *   UNIX:  define this if the program is being run on a unix-based system,    *
 
 *   which causes the executable to use unix-specific runtime utilities.       *
 
 *                                                                             *
 
 *   CPUS=N:  this sets up data structures to the appropriate size to support  *
 
 *   up to N simultaneous search engines.  note that you can set this to a     *
 
 *   value larger than the max processors you currently have, because the mt=n *
 
 *   command (added to the command line or your crafty.rc/.craftyrc file) will *
 
 *   control how many threads are actually spawned.                            *
 
 *                                                                             *
 
 *******************************************************************************
 
 */
 
/* *INDENT-OFF* */
 
 
 
#if defined(AFFINITY)
 
#  define _GNU_SOURCE
 
#  include <sched.h>
 
#endif
 
#if defined(UNIX)
 
#  define _GNU_SOURCE
 
#  if (CPUS > 1)
 
#    include <pthread.h>
 
#  endif
 
#  include <unistd.h>
 
#  include <sys/types.h>
 
#  include <sys/stat.h>
 
#endif
 
#include <stdint.h>
 
#include <inttypes.h>
 
#include <time.h>
 
#include <stdio.h>
 
#include <assert.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#if !defined(TYPES_INCLUDED)
 
#  define TYPES_INCLUDED
 
#  if !defined (UNIX)
 
#    define RESTRICT __restrict
 
#  else
 
#    define RESTRICT
 
#  endif
 
#  if !defined(CPUS)
 
#    define CPUS 1
 
#  endif
 
#  if !defined(UNIX)
 
#    include <windows.h>
 
#    include <process.h>
 
#  endif
 
#  define CDECL
 
#  define STDCALL
 
/* Provide reasonable defaults for UNIX systems. */
 
#  if !defined(UNIX)
 
#    undef  STDCALL
 
#    define STDCALL __stdcall
 
#    ifdef  VC_INLINE32
 
#      undef  CDECL
 
#      define CDECL __cdecl
 
#    endif
 
#  endif
 
#  if !defined(BOOKDIR)
 
#    define   BOOKDIR      "."
 
#  endif
 
#  if !defined(LOGDIR)
 
#    define   LOGDIR       "."
 
#  endif
 
#  if !defined(TBDIR)
 
#    define   TBDIR        "./TB"
 
#  endif
 
#  if !defined(RCDIR)
 
#    define   RCDIR        "."
 
#  endif
 
#  include "lock.h"
 
#  define MAXPLY                                 129
 
#  define MAX_TC_NODES                       3000000
 
#  define MAX_BLOCKS                       64 * CPUS
 
#  define BOOK_CLUSTER_SIZE                     8000
 
#  define MERGE_BLOCK                           1000
 
#  define SORT_BLOCK                         4000000
 
#  define LEARN_INTERVAL                          10
 
#  define LEARN_COUNTER_BAD                      -80
 
#  define LEARN_COUNTER_GOOD                    +100
 
#  define MATE                                 32768
 
#  define PAWN_VALUE                             100
 
#  define KNIGHT_VALUE                           305
 
#  define BISHOP_VALUE                           305
 
#  define ROOK_VALUE                             490
 
#  define QUEEN_VALUE                           1000
 
#  define KING_VALUE                           40000
 
#  if !defined(CLOCKS_PER_SEC)
 
#    define CLOCKS_PER_SEC 1000000
 
#  endif
 
typedef enum {
 
  A1, B1, C1, D1, E1, F1, G1, H1,
 
  A2, B2, C2, D2, E2, F2, G2, H2,
 
  A3, B3, C3, D3, E3, F3, G3, H3,
 
  A4, B4, C4, D4, E4, F4, G4, H4,
 
  A5, B5, C5, D5, E5, F5, G5, H5,
 
  A6, B6, C6, D6, E6, F6, G6, H6,
 
  A7, B7, C7, D7, E7, F7, G7, H7,
 
  A8, B8, C8, D8, E8, F8, G8, H8,
 
  BAD_SQUARE
 
} squares;
 
typedef enum { FILEA, FILEB, FILEC, FILED, FILEE, FILEF, FILEG, FILEH } files;
 
typedef enum { RANK1, RANK2, RANK3, RANK4, RANK5, RANK6, RANK7, RANK8 } ranks;
 
typedef enum { empty = 0, occupied = 0, pawn = 1, knight = 2, bishop = 3,
 
  rook = 4, queen = 5, king = 6
 
} PIECE;
 
typedef enum { black = 0, white = 1 } COLOR;
 
typedef enum { mg = 0, eg = 1 } PHASE;
 
typedef enum { empty_v = 0, pawn_v = 1, knight_v = 3,
 
               bishop_v = 3, rook_v = 5, queen_v = 9, king_v = 99
 
} PIECE_V;
 
typedef enum { serial = 0, parallel = 1} SEARCH_MODE;
 
typedef enum { think = 1, puzzle = 2, book = 3, annotate = 4 } SEARCH_TYPE;
 
typedef enum { normal_mode, tournament_mode } PLAYING_MODE;
 
typedef struct {
 
  int8_t castle[2];
 
  uint8_t enpassant_target;
 
  uint8_t reversible;
 
} SEARCH_POSITION;
 
typedef struct {
 
  int move1;
 
  int move2;
 
} KILLER;
 
typedef struct {
 
  uint64_t pieces[7];
 
} BB_PIECES;
 
typedef struct {
 
  BB_PIECES color[2];
 
  uint64_t hash_key;
 
  uint64_t pawn_hash_key;
 
  int material_evaluation;
 
  int kingsq[2];
 
  int8_t board[64];
 
  char pieces[2][7];
 
  char total_all_pieces;
 
} POSITION;
 
typedef struct {
 
  uint64_t word1;
 
  uint64_t word2;
 
} HASH_ENTRY;
 
typedef struct {
 
  uint64_t key;
 
  int32_t score_mg, score_eg;
 
  unsigned char defects_k[2];
 
  unsigned char defects_m[2];
 
  unsigned char defects_q[2];
 
  unsigned char passed[2];
 
} PAWN_HASH_ENTRY;
 
typedef struct {
 
  uint64_t entry[3];
 
} PXOR;
 
typedef struct {
 
  int path[MAXPLY];
 
  int pathh;
 
  int pathl;
 
  int pathd;
 
  int pathv;
 
} PATH;
 
typedef struct {
 
  uint64_t path_sig;
 
  int hash_pathl;
 
  int hash_path_age;
 
  int hash_path_moves[MAXPLY];
 
} HPATH_ENTRY;
 
typedef struct {
 
  int phase;
 
  int order;
 
  int remaining;
 
  unsigned *last;
 
  unsigned done[10];
 
  unsigned *exclude;
 
} NEXT_MOVE;
 
/*
 
   root_move.status:
 
 
 
   xxx1 = failed low this iteration
 
   xx1x = failed high this iteration
 
   x1xx = don't search in parallel or reduce
 
   1xxx = move has been searched
 
 */
 
typedef struct {
 
  int move;
 
  unsigned status;
 
  int bm_age;
 
  PATH path;
 
} ROOT_MOVE;
 
#  if !defined(UNIX)
 
#    pragma pack(4)
 
#  endif
 
typedef struct {
 
  uint64_t position;
 
  unsigned status_played;
 
  float learn;
 
} BOOK_POSITION;
 
#  if !defined(UNIX)
 
#    pragma pack()
 
#  endif
 
typedef struct {
 
  unsigned char position[8];
 
  unsigned char status;
 
  unsigned char percent_play;
 
} BB_POSITION;
 
struct personality_term {
 
  char *description;
 
  int type;
 
  int size;
 
  void *value;
 
};
 
struct autotune {
 
  unsigned int min;
 
  unsigned int max;
 
  unsigned int increment;
 
  char description[64];
 
  char command[16];
 
  unsigned int *parameter;
 
};
 
typedef struct tree {
 
/* commonly used variables */
 
  SEARCH_POSITION status[MAXPLY + 3];
 
  NEXT_MOVE next_status[MAXPLY];
 
  KILLER killers[MAXPLY];
 
  POSITION position;
 
  uint64_t save_hash_key[MAXPLY + 3];
 
  uint64_t save_pawn_hash_key[MAXPLY + 3];
 
  uint64_t rep_list[256];
 
  int curmv[MAXPLY];
 
  int phase[MAXPLY];
 
  int hash_move[MAXPLY];
 
  unsigned *last[MAXPLY];
 
  unsigned move_list[5120];
 
  PATH pv[MAXPLY];
 
/* variables used by Evaluate() */
 
  PAWN_HASH_ENTRY pawn_score;
 
  int tropism[2];
 
  int dangerous[2];
 
  uint64_t all_pawns;
 
  int score_mg, score_eg;
 
/* statistical counters */
 
  uint64_t nodes_searched;
 
  uint64_t fail_highs;
 
  uint64_t fail_high_first_move;
 
  uint64_t evaluations;
 
  uint64_t egtb_probes;
 
  uint64_t egtb_hits;
 
  uint64_t extensions_done;
 
  uint64_t qchecks_done;
 
  uint64_t moves_fpruned;
 
  uint64_t moves_mpruned;
 
  uint64_t LMR_done[16];
 
  uint64_t null_done[16];
 
/* thread stuff */
 
  lock_t lock;
 
  int thread_id;
 
  volatile int joinable;
 
  volatile int joined;
 
  volatile int stop;
 
  volatile int nprocs;
 
  int alpha;
 
  int beta;
 
  volatile int value;
 
  int wtm;
 
  int depth;
 
  int ply;
 
  int in_check;
 
  int *searched;
 
  int cutmove;
 
  struct tree *volatile siblings[CPUS], *parent;
 
/* rarely accessed */
 
  char root_move_text[16];
 
  char remaining_moves_text[16];
 
} TREE;
 
typedef struct thread {
 
  TREE *tree;
 
  uint64_t blocks;
 
  uint64_t max_blocks;
 
  unsigned int idle;
 
  volatile unsigned int terminate;
 
  char filler[40];
 
} THREAD;
 
/*
 
   DO NOT modify these.  these are constants, used in multiple modules.
 
   modification may corrupt the search in any number of ways, all bad.
 
 */
 
#  define WORTHLESS                    0
 
#  define UPPER                        1
 
#  define LOWER                        2
 
#  define EXACT                        3
 
#  define HASH_MISS                    0
 
#  define HASH_HIT                     1
 
#  define AVOID_NULL_MOVE              2
 
#  define NO_NULL                      0
 
#  define DO_NULL                      1
 
#  define NONE                         0
 
#  define NULL_MOVE                    1
 
#  define DO_NOT_REDUCE                1
 
#  define HASH                         2
 
#  define GENERATE_CAPTURES            3
 
#  define CAPTURES                     4
 
#  define KILLER1                      5
 
#  define KILLER2                      6
 
#  define KILLER3                      7
 
#  define KILLER4                      8
 
#  define COUNTER_MOVE1                9
 
#  define COUNTER_MOVE2               10
 
#  define MOVE_PAIR1                  11
 
#  define MOVE_PAIR2                  12
 
#  define GENERATE_QUIET              13
 
#  define HISTORY                     14
 
#  define REMAINING                   15
 
#  define EVALUATION                  16
 
#  define ILLEGAL                      0
 
#  define LEGAL                        1
 
#  define IN_WINDOW                    2
 
#  define FAIL_HIGH                    3
 
#if /*defined(UNIX) &&*/ !defined(INLINEASM) // Pierre-Marie Baty -- we also use them on Windows...
 
int CDECL PopCnt(uint64_t);
 
int CDECL MSB(uint64_t);
 
int CDECL LSB(uint64_t);
 
#endif
 
void AlignedMalloc(void **, int, size_t);
 
void AlignedRemalloc(void **, int, size_t);
 
void Analyze(void);
 
void Annotate(void);
 
void AnnotateHeaderHTML(char *, FILE *);
 
void AnnotateFooterHTML(FILE *);
 
void AnnotatePositionHTML(TREE *RESTRICT, int, FILE *);
 
char *AnnotateVtoNAG(int, int, int, int);
 
void AnnotateHeaderTeX(FILE *);
 
void AnnotateFooterTeX(FILE *);
 
void AnnotatePositionTeX(TREE *, int, FILE *);
 
uint64_t atoiKMB(char *);
 
int Attacks(TREE *RESTRICT, int, int);
 
uint64_t Attacked(TREE *RESTRICT, int, uint64_t);
 
uint64_t AttacksFrom(TREE *RESTRICT, int, int);
 
uint64_t AttacksTo(TREE *RESTRICT, int);
 
void AutoTune(int, char **);
 
int Bench(int, int);
 
int Bench_PGO(int, int);
 
int Book(TREE *RESTRICT, int);
 
void BookClusterIn(FILE *, int, BOOK_POSITION *);
 
void BookClusterOut(FILE *, int, BOOK_POSITION *);
 
int BookIn32(unsigned char *);
 
float BookIn32f(unsigned char *);
 
uint64_t BookIn64(unsigned char *);
 
int BookMask(char *);
 
unsigned char *BookOut32(int);
 
unsigned char *BookOut32f(float);
 
unsigned char *BookOut64(uint64_t);
 
int BookPonderMove(TREE *RESTRICT, int);
 
void Bookup(TREE *RESTRICT, int, char **);
 
void BookSort(BB_POSITION *, int, int);
 
int BookupCompare(const void *, const void *);
 
BB_POSITION BookupNextPosition(int, int);
 
int CheckInput(void);
 
void ClearHashTableScores(void);
 
int ComputeDifficulty(int, int);
 
void CopyFromParent(TREE *RESTRICT);
 
void CopyToParent(TREE *RESTRICT, TREE *RESTRICT, int);
 
void CraftyExit(int);
 
void DisplayArray(int *, int);
 
void DisplayArrayX2(int *, int *, int);
 
void DisplayBitBoard(uint64_t);
 
void Display2BitBoards(uint64_t, uint64_t);
 
void DisplayChessBoard(FILE *, POSITION);
 
char *DisplayEvaluation(int, int);
 
char *DisplayEvaluationKibitz(int, int);
 
void DisplayFT(int, int, int);
 
char *DisplayHHMM(unsigned);
 
char *DisplayHHMMSS(unsigned);
 
char *DisplayKMB(uint64_t, int);
 
void DisplayFail(TREE *RESTRICT, int, int, int, int, int, int, int);
 
char *DisplayPath(TREE *RESTRICT, int, PATH *);
 
void DisplayPV(TREE *RESTRICT, int, int, int, PATH *, int);
 
char *DisplayTime(unsigned);
 
char *Display2Times(unsigned);
 
char *DisplayTimeKibitz(unsigned);
 
void DisplayChessMove(char *, int);
 
int Drawn(TREE *RESTRICT, int);
 
void Edit(void);
 
#  if !defined(NOEGTB)
 
int EGTBProbe(TREE *RESTRICT, int, int, int *);
 
void EGTBPV(TREE *RESTRICT, int);
 
#  endif
 
int Evaluate(TREE *RESTRICT, int, int, int, int);
 
void EvaluateBishops(TREE *RESTRICT, int);
 
void EvaluateCastling(TREE *RESTRICT, int, int);
 
int EvaluateDraws(TREE *RESTRICT, int, int, int);
 
int EvaluateHasOpposition(int, int, int);
 
void EvaluateKing(TREE *RESTRICT, int, int);
 
int EvaluateKingsFile(TREE * RESTRICT, int, int, int);
 
void EvaluateKnights(TREE *RESTRICT, int);
 
void EvaluateMate(TREE *RESTRICT, int);
 
void EvaluateMaterial(TREE *RESTRICT, int);
 
void EvaluatePassedPawns(TREE *RESTRICT, int, int);
 
void EvaluatePassedPawnRaces(TREE *RESTRICT, int);
 
void EvaluatePawns(TREE *RESTRICT, int);
 
void EvaluateQueens(TREE *RESTRICT, int);
 
void EvaluateRooks(TREE *RESTRICT, int);
 
int EvaluateWinningChances(TREE *RESTRICT, int, int);
 
void EVTest(char *);
 
int Exclude(TREE *RESTRICT, int, int);
 
int FindBlockID(TREE *RESTRICT);
 
char *FormatPV(TREE *RESTRICT, int, PATH);
 
int FTbSetCacheSize(void *, unsigned long);
 
int GameOver(int);
 
unsigned *GenerateCaptures(TREE *RESTRICT, int, int, unsigned *);
 
unsigned *GenerateCheckEvasions(TREE *RESTRICT, int, int, unsigned *);
 
unsigned *GenerateChecks(TREE *RESTRICT, int, unsigned *);
 
unsigned *GenerateNoncaptures(TREE *RESTRICT, int, int, unsigned *);
 
TREE *GetBlock(TREE *, int);
 
void Initialize(void);
 
void InitializeAttackBoards(void);
 
void InitializeChessBoard(TREE *);
 
int InitializeGetLogID();
 
void InitializeHashTables(int);
 
void InitializeKillers(void);
 
void InitializeKingSafety(void);
 
void InitializeMagic(void);
 
uint64_t InitializeMagicBishop(int, uint64_t);
 
uint64_t InitializeMagicRook(int, uint64_t);
 
uint64_t InitializeMagicOccupied(int *, int, uint64_t);
 
void InitializeMasks(void);
 
void InitializePawnMasks(void);
 
void InitializeReductions(void);
 
void InitializeSMP(void);
 
int IInitializeTb(char *);
 
int InputMove(TREE *RESTRICT, int, int, int, int, char *);
 
int InputMoveICS(TREE *RESTRICT, int, int, int, int, char *);
 
uint64_t InterposeSquares(int, int, int);
 
void Interrupt(int);
 
int InvalidPosition(TREE *RESTRICT);
 
int Iterate(int, int, int);
 
int Join(int64_t);
 
void Kibitz(int, int, int, int, int, uint64_t, int, int, char *);
 
void History(TREE *RESTRICT, int, int, int, int, int*);
 
int KingPawnSquare(int, int, int, int);
 
int LearnAdjust(int);
 
void LearnBook(void);
 
int LearnFunction(int, int, int, int);
 
void LearnValue(int, int);
 
void MakeMove(TREE *RESTRICT, int, int, int);
 
void MakeMoveRoot(TREE *RESTRICT, int, int);
 
void NewGame(int);
 
int NextMove(TREE *RESTRICT, int, int, int, int);
 
int NextRootMove(TREE *RESTRICT, TREE *RESTRICT, int);
 
int NextRootMoveParallel(void);
 
void NextSort(TREE *RESTRICT, int);
 
int Option(TREE *RESTRICT);
 
int OptionMatch(char *, char *);
 
void OptionPerft(TREE *RESTRICT, int, int, int);
 
void Output(TREE *RESTRICT);
 
char *OutputMove(TREE *RESTRICT, int, int, int);
 
int ParseTime(char *);
 
void Pass(void);
 
int PinnedOnKing(TREE *RESTRICT, int, int);
 
int Ponder(int);
 
void Print(int, char *, ...);
 
int HashProbe(TREE *RESTRICT, int, int, int, int, int, int*);
 
void HashStore(TREE *RESTRICT, int, int, int, int, int, int);
 
void HashStorePV(TREE *RESTRICT, int, int);
 
int Quiesce(TREE *RESTRICT, int, int, int, int, int);
 
int QuiesceEvasions(TREE *RESTRICT, int, int, int, int);
 
unsigned Random32(void);
 
uint64_t Random64(void);
 
int Read(int, char *);
 
int ReadChessMove(TREE *RESTRICT, FILE *, int, int);
 
void ReadClear(void);
 
unsigned ReadClock(void);
 
int ReadPGN(FILE *, int);
 
int ReadNextMove(TREE *RESTRICT, char *, int, int);
 
int ReadParse(char *, char *args[], char *);
 
int ReadInput(void);
 
int Repeat(TREE *RESTRICT, int);
 
int Repeat3x(TREE *RESTRICT);
 
void ResignOrDraw(TREE *RESTRICT, int);
 
void RestoreGame(void);
 
void RootMoveList(int);
 
int Search(TREE *RESTRICT, int, int, int, int, int, int, int);
 
int SearchMove(TREE *RESTRICT, int, int, int, int, int, int, int, int, int);
 
int SearchMoveList(TREE *RESTRICT, int, int, int, int, int, int *, int, int, int);
 
int SearchNull(TREE * RESTRICT, int, int, int, int);
 
void Trace(TREE *RESTRICT, int, int, int, int, int, const char *, int, int, int);
 
void SetBoard(TREE *, int, char **, int);
 
void SetChessBitBoards(TREE *);
 
void SharedFree(void *address);
 
void SortRootMoves(void);
 
int Split(TREE *RESTRICT);
 
int StrCnt(char *, char);
 
int SEE(TREE *RESTRICT, int, int);
 
int SEEO(TREE *RESTRICT, int, int);
 
void Test(char *, FILE *, int, int);
 
void TestEPD(char *, FILE *, int, int);
 
void ThreadAffinity(int);
 
void *STDCALL ThreadInit(void *);
 
#  if !defined(UNIX)
 
void ThreadMalloc(int64_t);
 
#  endif
 
int ThreadSplit(TREE *RESTRICT, int, int, int, int, int);
 
void ThreadStop(TREE *RESTRICT);
 
void ThreadTrace(TREE * RESTRICT, int, int);
 
int ThreadWait(int, TREE *RESTRICT);
 
int Threat(TREE *, int, int, int, int);
 
void TimeAdjust(int, int);
 
int TimeCheck(TREE *RESTRICT, int);
 
void TimeSet(int);
 
void UnmakeMove(TREE *RESTRICT, int, int, int);
 
int ValidMove(TREE *RESTRICT, int, int, int);
 
int VerifyMove(TREE *RESTRICT, int, int, int);
 
void ValidatePosition(TREE *RESTRICT, int, int, char *);
 
void WaitForAllThreadsInitialized(void);
 
#  if !defined(UNIX)
 
extern void *WinMallocInterleaved(size_t, int);
 
extern void WinFreeInterleaved(void *, size_t);
 
#    define MallocInterleaved(cBytes, cThreads)     \
 
       WinMallocInterleaved(cBytes, cThreads)
 
#    define FreeInterleaved(pMemory, cBytes)        \
 
       WinFreeInterleaved(pMemory, cBytes)
 
#  else
 
#    if defined(NUMA)
 
#      define MallocInterleaved(cBytes, cThreads) numa_alloc_interleaved(cBytes)
 
#      define FreeInterleaved(pMemory, cBytes)          numa_free(pMemory, 1)
 
#    else
 
#      define MallocInterleaved(cBytes, cThreads) malloc(cBytes)
 
#      define FreeInterleaved(pMemory, cBytes)          free(pMemory)
 
#    endif
 
#  endif
 
#  define Abs(a)    (((a) > 0) ? (a) : -(a))
 
#  define Max(a,b)  (((a) > (b)) ? (a) : (b))
 
#  define Min(a,b)  (((a) < (b)) ? (a) : (b))
 
#  define Sign(a)   ((a) < 0 ? -1 : +1)
 
#  define FileDistance(a,b) abs(File(a) - File(b))
 
#  define RankDistance(a,b) abs(Rank(a) - Rank(b))
 
#  define Distance(a,b) Max(FileDistance(a,b), RankDistance(a,b))
 
#  define DrawScore(side)                  (draw_score[side])
 
#  define PopCnt8Bit(a) (pop_cnt_8bit[a])
 
#  define MSB8Bit(a) (msb_8bit[a])
 
#  define LSB8Bit(a) (lsb_8bit[a])
 
#  define HistoryIndex(side, m) ((side << 9) + (Piece(m) << 6) + To(m))
 
/*
 
   side = side to move
 
   mptr = pointer into move list
 
   m = bit vector of to squares to unpack
 
   t = pre-computed from + moving piece
 
 */
 
#  define Extract(side, mptr, m, t)                                         \
 
  for ( ; m ; Clear(to, m)) {                                               \
 
    to = MostAdvanced(side, m);                                             \
 
    *mptr++ = t | (to << 6) | (Abs(PcOnSq(to)) << 15);                      \
 
  }
 
#  define Check(side) Attacks(tree, Flip(side), KingSQ(side))
 
#  define Attack(from,to) (!(intervening[from][to] & OccupiedSquares))
 
#  define BishopAttacks(square, occ) *(magic_bishop_indices[square]+((((occ)&magic_bishop_mask[square])*magic_bishop[square])>>magic_bishop_shift[square]))
 
#  define BishopMobility(square, occ) *(magic_bishop_mobility_indices[square]+((((occ)&magic_bishop_mask[square])*magic_bishop[square])>>magic_bishop_shift[square]))
 
#  define KingAttacks(square) king_attacks[square]
 
#  define KnightAttacks(square) knight_attacks[square]
 
#  define PawnAttacks(side, square)   pawn_attacks[side][square]
 
#  define Reversible(p)               (tree->status[p].reversible)
 
#  define RookAttacks(square, occ) *(magic_rook_indices[square]+((((occ)&magic_rook_mask[square])*magic_rook[square])>>magic_rook_shift[square]))
 
#  define RookMobility(square, occ) *(magic_rook_mobility_indices[square]+((((occ)&magic_rook_mask[square])*magic_rook[square])>>magic_rook_shift[square]))
 
#  define QueenAttacks(square, occ)   (BishopAttacks(square, occ)|RookAttacks(square, occ))
 
#  define Rank(x)        ((x)>>3)
 
#  define File(x)        ((x)&7)
 
#  define Flip(x)        ((x)^1)
 
#  define MostAdvanced(side, squares) ((side) ? MSB(squares) : LSB(squares))
 
#  define LeastAdvanced(side, squares) ((side) ? LSB(squares) : MSB(squares))
 
#  define MinMax(side, v1, v2) ((side) ? Min((v1), (v2)) : Max((v1), (v2)))
 
#  define InFront(side, k, p) ((side) ? k > p : k < p)
 
#  define Behind(side, k, p) ((side) ? k < p : k > p)
 
#  define Passed(sq, wtm)        (!(mask_passed[wtm][sq] & Pawns(Flip(wtm))))
 
#  define RankAttacks(a) (RookAttacks(a, OccupiedSquares) & rank_mask[Rank(a)])
 
#  define FileAttacks(a) (RookAttacks(a, OccupiedSquares) & file_mask[File(a)])
 
#  define Diaga1Attacks(a) (BishopAttacks(a, OccupiedSquares) & (plus9dir[a] | minus9dir[a]))
 
#  define Diagh1Attacks(a) (BishopAttacks(a, OccupiedSquares) & (plus7dir[a] | minus7dir[a]))
 
#  define InterposeSquares(kingsq, checksq) intervening[kingsq][checksq]
 
/*
 
   the following macros are used to extract the pieces of a move that are
 
   kept compressed into the rightmost 21 bits of a simple integer.
 
 */
 
#  define From(a)               ((a) & 63)
 
#  define To(a)                 (((a)>>6) & 63)
 
#  define Piece(a)              (((a)>>12) & 7)
 
#  define Captured(a)           (((a)>>15) & 7)
 
#  define Promote(a)            (((a)>>18) & 7)
 
#  define Move(a)               (a & 0x1fffff)
 
#  define SortV(a)              (a >> 21)
 
#  define CaptureOrPromote(a)   (((a)>>15) & 63)
 
#  define PawnPush(c, a)        (Piece(a) == pawn &&                          \
 
                                     rankflip[c][Rank(To(a))] >= RANK6        \
 
                                     && !(mask_passed[c][To(a)] &             \
 
                                          Pawns(Flip(c))))
 
#  define CastleMove(c, a)       (Piece(a) == king && Abs(File(To(a)) -       \
 
                                     File(From(a))) > 1)
 
#  define SetMask(a)             (set_mask[a])
 
#  define ClearMask(a)           (clear_mask[a])
 
#  define Pawns(c)               (tree->position.color[c].pieces[pawn])
 
#  define Knights(c)             (tree->position.color[c].pieces[knight])
 
#  define Bishops(c)             (tree->position.color[c].pieces[bishop])
 
#  define Rooks(c)               (tree->position.color[c].pieces[rook])
 
#  define Queens(c)              (tree->position.color[c].pieces[queen])
 
#  define Kings(c)               (tree->position.color[c].pieces[king])
 
#  define KingSQ(c)              (tree->position.kingsq[c])
 
#  define Occupied(c)            (tree->position.color[c].pieces[occupied])
 
#  define Pieces(c, p)           (tree->position.color[c].pieces[p])
 
#  define TotalPieces(c, p)      (tree->position.pieces[c][p])
 
#  define PieceValues(c, p)      (piece_values[c][p])
 
#  define TotalAllPieces         (tree->position.total_all_pieces)
 
#  define Material               (tree->position.material_evaluation)
 
#  define MaterialSTM(side)      ((side) ? Material : -Material)
 
#  define MateScore(s)           (Abs(s) > 32000)
 
#  define Castle(ply, c)         (tree->status[ply].castle[c])
 
#  define HashKey                (tree->position.hash_key)
 
#  define PawnHashKey            (tree->position.pawn_hash_key)
 
#  define EnPassant(ply)         (tree->status[ply].enpassant_target)
 
#  define EnPassantTarget(ply)   (EnPassant(ply) ? SetMask(EnPassant(ply)) : 0)
 
#  define PcOnSq(sq)             (tree->position.board[sq])
 
#  define OccupiedSquares        (Occupied(white) | Occupied(black))
 
#  define Color(square)       (square_color[square] ? dark_squares : ~dark_squares)
 
#  define SideToMove(c)          ((c) ? "White" : "Black")
 
/*
 
   the following macros are used to Set and Clear a specific bit in the
 
   second argument.  this is done to make the code more readable, rather
 
   than to make it faster.
 
 */
 
#  define ClearSet(a,b)         b=((a) ^ (b))
 
#  define Clear(a,b)            b=ClearMask(a) & (b)
 
#  define Set(a,b)              b=SetMask(a) | (b)
 
/*
 
   the following macros are used to update the hash signatures.
 
 */
 
#  define Hash(stm,piece,square)     (HashKey^=randoms[stm][piece][square])
 
#  define HashP(stm,square)          (PawnHashKey^=randoms[stm][pawn][square])
 
#  define HashCastle(stm,direction)  (HashKey^=castle_random[stm][direction])
 
#  define HashEP(sq)                 (HashKey^=enpassant_random[sq])
 
#  define SavePV(tree,ply,ph)        do {                                     \
 
        tree->pv[ply-1].path[ply-1]=tree->curmv[ply-1];                       \
 
        tree->pv[ply-1].pathl=ply;                                            \
 
        tree->pv[ply-1].pathh=ph;                                             \
 
        tree->pv[ply-1].pathd=iteration;} while(0)
 
#  if defined(INLINEASM)
 
#    include "inline.h"
 
#  endif
 
#endif
 
/* *INDENT-ON* */