diff options
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 2981 |
1 files changed, 2981 insertions, 0 deletions
diff --git a/src/chess.h b/src/chess.h new file mode 100755 index 0000000..c815701 --- /dev/null +++ b/src/chess.h @@ -0,0 +1,2981 @@ +/** + +Copyright (c) Scott Gasch + +Module Name: + + chess.h + +Abstract: + +Author: + + Scott Gasch ([email protected]) 7 Apr 2004 + +Revision History: + + $Id: chess.h 354 2008-06-30 05:10:08Z scott $ + +**/ + +#ifndef CHESS_ +#define CHESS_ + +#include "compiler.h" + +// +// Datatype wrappers +// +#define MIN_CHAR (0x80) +#define MAX_CHAR (0x7f) +typedef char CHAR; + +#define MIN_BYTE (0x00) +#define MAX_BYTE (0xff) +typedef unsigned char BYTE; + +#define MIN_UCHAR (0x00) +#define MAX_UCHAR (0xff) +typedef unsigned char UCHAR; +#define CAN_FIT_IN_UCHAR(x) ((x) <= MAX_UCHAR) + +#define MIN_SHORT (0x8000) +#define MAX_SHORT (0x7fff) +typedef signed short SHORT; + +#define MIN_USHORT (0x0000) +#define MAX_USHORT (0xffff) +typedef unsigned short USHORT; +#define CAN_FIT_IN_USHORT(x) ((x) <= MAX_USHORT) + +#define MIN_WORD (0x0000) +#define MAX_WORD (0xffff) +typedef unsigned short WORD; + +#define MIN_INT (0x80000000) +#define MAX_INT (0x7fffffff) +typedef signed int INT; + +#define MIN_DWORD (0x00000000) +#define MAX_DWORD (0xffffffff) +typedef unsigned int DWORD; + +#define MIN_UINT (0x00000000) +#define MAX_UINT (0xffffffff) +typedef unsigned int UINT; + +#define MIN_ULONG (0x00000000) +#define MAX_ULONG (0xffffffff) +typedef unsigned int ULONG; + +#define MIN_INT64 (0x8000000000000000) +#define MAX_INT64 (0x7fffffffffffffff) +typedef signed COMPILER_LONGLONG INT64; + +#define MIN_UINT64 (0x0000000000000000) +#define MAX_UINT64 (0xffffffffffffffff) +typedef unsigned COMPILER_LONGLONG UINT64; + +#define MIN_BITBOARD (0x0000000000000000) +#define MAX_BITBOARD (0xffffffffffffffff) +typedef UINT64 BITBOARD; + +#define MIN_BITV MIN_UINT +#define MAX_BITV MAX_UINT +typedef unsigned int BITV; + +#define MIN_FLAG MIN_UINT +#define MAX_FLAG MAX_UINT +typedef unsigned int FLAG; +#define IS_VALID_FLAG(x) (((x) == TRUE) || ((x) == FALSE)) + +typedef unsigned int COOR; +typedef unsigned int PIECE; +typedef signed int SCORE; + +#define BIT1 (0x1) +#define BIT2 (0x2) +#define BIT3 (0x4) +#define BIT4 (0x8) +#define BIT5 (0x10) +#define BIT6 (0x20) +#define BIT7 (0x40) +#define BIT8 (0x80) +#define BIT9 (0x100) +#define BIT10 (0x200) +#define BIT11 (0x400) +#define BIT12 (0x800) +#define BIT13 (0x1000) +#define BIT14 (0x2000) +#define BIT15 (0x4000) +#define BIT16 (0x8000) +#define BIT17 (0x10000) +#define BIT18 (0x20000) +#define BIT19 (0x40000) +#define BIT20 (0x80000) +#define BIT21 (0x100000) +#define BIT22 (0x200000) +#define BIT23 (0x400000) +#define BIT24 (0x800000) +#define BIT25 (0x1000000) +#define BIT26 (0x2000000) +#define BIT27 (0x4000000) +#define BIT28 (0x8000000) +#define BIT29 (0x10000000) +#define BIT30 (0x20000000) +#define BIT31 (0x40000000) +#define BIT32 (0x80000000) + +typedef struct _DLIST_ENTRY +{ + struct _DLIST_ENTRY *pFlink; + struct _DLIST_ENTRY *pBlink; +} DLIST_ENTRY; + +// +// Constants +// +#define YES (1) +#define NO (0) +#ifndef TRUE +#define TRUE (YES) +#endif +#ifndef FALSE +#define FALSE (NO) +#endif + +// +// Calculate the length of an array (i.e. number of elements) +// +#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) +#define COMMAND(x) \ + void (x)(CHAR *szInput, ULONG argc, CHAR *argv[], POSITION *pos) +#define MB (1024 * 1024) + +// +// Calculate the address of the base of the structure given its type, and an +// address of a field within the structure. +// +#ifndef OFFSET_OF +#define OFFSET_OF(field, type) \ + (ULONG)(&((type *)0)->field) +#endif +#ifndef CONTAINING_STRUCT +#define CONTAINING_STRUCT(address, type, field) \ + ((type *)((BYTE *)(address) - (BYTE *)(OFFSET_OF(field, type)))) +#endif + +#define WHITE (1) +#define BLACK (0) +#define BAD_COLOR (2) +#define IS_VALID_COLOR(x) (((x) == WHITE) || ((x) == BLACK)) +#define FOREACH_COLOR(x) for((x) = BLACK; (x) < BAD_COLOR; (x)++) +#define RANDOM_COLOR (rand() & 1) +#define FLIP(color) ((color) ^ 1) +#define COLOR_NAME(color) (((color) == WHITE) ? "white" : "black") + +#define MAX_MOVES_PER_PLY (218) +#define MAX_PLY_PER_SEARCH (64) +#define MAX_MOVES_PER_GAME (1024) +#define SMALL_STRING_LEN_CHAR (256) +#define MEDIUM_STRING_LEN_CHAR (8192) +#define BIG_STRING_LEN_CHAR (16384) + +#define QUARTER_PLY 16 +#define HALF_PLY 32 +#define THREE_QUARTERS_PLY 48 +#define ONE_PLY 64 +#define TWO_PLY 128 +#define THREE_PLY 192 +#define FOUR_PLY 256 +#define MAX_DEPTH_PER_SEARCH (MAX_PLY_PER_SEARCH * ONE_PLY) + +#define IS_VALID_DEPTH(x) (((x) >= 0) && \ + ((x) <= MAX_DEPTH_PER_SEARCH) && \ + (((x) & 0xfffff00f) == 0)) + +#define INFINITY (MAX_SHORT) +#define INVALID_SCORE (INFINITY + 1) +#define IS_VALID_SCORE(x) (((x) >= -INFINITY) && \ + ((x) <= +INFINITY)) +#define NMATE (+INFINITY - 200) +#define MATED_SCORE(ply) (-INFINITY + (ply)) + +#define IS_A_POWER_OF_2(x) (((x) & (x - 1)) == 0) +// +// Program version number +// +#define VERSION "1.00" +#define REVISION "$Id: chess.h 354 2008-06-30 05:10:08Z scott $\n" + +// +// Function decorators +// +#define IN +#define OUT +#define INOUT +#define UNUSED +#define NOTHING + +// ---------------------------------------------------------------------- +// +// PIECE: +// +// a piece (4 bits) = type (3 bits) + color (1 bit) +// +// 3 1 0 +// . . . . +// | | | +// type C +// +#define KING (6) // 110X +#define QUEEN (5) // 101X +#define ROOK (4) // 100X +#define BISHOP (3) // 011X +#define KNIGHT (2) // 010X +#define PAWN (1) // 001X +#define EMPTY (0) // 000X + +// (WHATEVER << 1) +#define BLACK_PAWN (2) // 0010 +#define BLACK_KNIGHT (4) // 0100 +#define BLACK_BISHOP (6) // 0110 +#define BLACK_ROOK (8) // 1000 +#define BLACK_QUEEN (10) // 1010 +#define BLACK_KING (12) // 1100 + +// (WHATEVER << 1) | WHITE +#define WHITE_PAWN (3) // 0011 +#define WHITE_KNIGHT (5) // 0101 +#define WHITE_BISHOP (7) // 0111 +#define WHITE_ROOK (9) // 1001 +#define WHITE_QUEEN (11) // 1011 +#define WHITE_KING (13) // 1101 + +#define PIECE_TYPE(p) ((p) >> 1) +#define PIECE_COLOR(p) ((p) & WHITE) +#define RANDOM_PIECE (rand() % 12) + 2; +#define IS_PAWN(p) (((p) & 0xE) == BLACK_PAWN) +#define IS_KNIGHT(p) (((p) & 0xE) == BLACK_KNIGHT) +#define IS_BISHOP(p) (((p) & 0xE) == BLACK_BISHOP) +#define IS_ROOK(p) (((p) & 0xE) == BLACK_ROOK) +#define IS_QUEEN(p) (((p) & 0xE) == BLACK_QUEEN) +#define IS_KING(p) (((p) & 0xE) == BLACK_KING) +#define IS_KNIGHT_OR_KING(p) (((p) & 0x6) == 0x4) +#define IS_VALID_PIECE(p) ((PIECE_TYPE((p)) >= PAWN) && \ + (PIECE_TYPE((p)) <= KING)) +#define IS_WHITE_PIECE(p) ((p) & WHITE) +#define IS_BLACK_PIECE(p) (!IS_WHITE(p)) +#define OPPOSITE_COLORS(p, q) (((p) ^ (q)) & WHITE) +#define SAME_COLOR(p,q) (!OPPOSITE_COLORS(p, q)) +#define GET_COLOR(p) ((p) & WHITE) + +// ---------------------------------------------------------------------- +// +// a coordinate (8 bits) = rank + file (0x88) +// +// 7 4 3 0 +// . . . . . . . . +// | | | +// rank file +// | | +// | +--- 0-7 = file A thru file H +// | +// +------------ 0-7 = rank 1 thru rank 8 +// +// given a coordinate, C, if C & 0x88 then it is illegal (off board) +// +// +// 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 +// +---------------------------------------+ +// 8 | 00 |:01:| 02 |:03:| 04 |:05:| 06 |:07:| 0x00 +// 7 |:10:| 11 |:12:| 13 |:14:| 15 |:16:| 17 | 0x10 +// 6 | 20 |:21:| 22 |:23:| 24 |:25:| 26 |:27:| 0x20 +// 5 |:30:| 31 |:32:| 33 |:34:| 35 |:36:| 37 | 0x30 +// 4 | 40 |:41:| 42 |:43:| 44 |:45:| 46 |:47:| 0x40 +// 3 |:50:| 51 |:52:| 53 |:54:| 55 |:56:| 57 | 0x50 +// 2 | 60 |:61:| 62 |:63:| 64 |:65:| 66 |:67:| 0x60 +// 1 |:70:| 71 |:72:| 73 |:74:| 75 |:76:| 77 | 0x70 +// +---------------------------------------+ +// A B C D E F G H +// +#define A (0) +#define B (1) +#define C (2) +#define D (3) +#define E (4) +#define F (5) +#define G (6) +#define H (7) + +#define A8 (0x00) +#define B8 (0x01) +#define C8 (0x02) +#define D8 (0x03) +#define E8 (0x04) +#define F8 (0x05) +#define G8 (0x06) +#define H8 (0x07) + +#define A7 (0x10) +#define B7 (0x11) +#define C7 (0x12) +#define D7 (0x13) +#define E7 (0x14) +#define F7 (0x15) +#define G7 (0x16) +#define H7 (0x17) + +#define A6 (0x20) +#define B6 (0x21) +#define C6 (0x22) +#define D6 (0x23) +#define E6 (0x24) +#define F6 (0x25) +#define G6 (0x26) +#define H6 (0x27) + +#define A5 (0x30) +#define B5 (0x31) +#define C5 (0x32) +#define D5 (0x33) +#define E5 (0x34) +#define F5 (0x35) +#define G5 (0x36) +#define H5 (0x37) + +#define A4 (0x40) +#define B4 (0x41) +#define C4 (0x42) +#define D4 (0x43) +#define E4 (0x44) +#define F4 (0x45) +#define G4 (0x46) +#define H4 (0x47) + +#define A3 (0x50) +#define B3 (0x51) +#define C3 (0x52) +#define D3 (0x53) +#define E3 (0x54) +#define F3 (0x55) +#define G3 (0x56) +#define H3 (0x57) + +#define A2 (0x60) +#define B2 (0x61) +#define C2 (0x62) +#define D2 (0x63) +#define E2 (0x64) +#define F2 (0x65) +#define G2 (0x66) +#define H2 (0x67) + +#define A1 (0x70) +#define B1 (0x71) +#define C1 (0x72) +#define D1 (0x73) +#define E1 (0x74) +#define F1 (0x75) +#define G1 (0x76) +#define H1 (0x77) + +// TODO: if use this anywhere that matters, consider double loop +// and unrolling the inside loop to prevent the multiple +// continue for invalid squares +#define FOREACH_SQUARE(x) for((x) = (A8); (x) <= (H1); (x)++) + +#define IS_ON_BOARD(c) (!((c) & 0x88)) +#define RANDOM_COOR (rand() & 0x77) +#define FILE_RANK_TO_COOR(f, r) (((8 - (r)) << 4) | (f)) +#define RANK(c) (8 - ((c) >> 4)) +#define RANK1(c) (((c) & 0xF0) == 0x70) +#define RANK2(c) (((c) & 0xF0) == 0x60) +#define RANK3(c) (((c) & 0xF0) == 0x50) +#define RANK4(c) (((c) & 0xF0) == 0x40) +#define RANK5(c) (((c) & 0xF0) == 0x30) +#define RANK6(c) (((c) & 0xF0) == 0x20) +#define RANK7(c) (((c) & 0xF0) == 0x10) +#define RANK8(c) (((c) & 0xF0) == 0x00) +#define FILE(c) ((c) & 0x0F) +#define FILEA(c) (((c) & 0x0F) == 0x00) +#define FILEB(c) (((c) & 0x0F) == 0x01) +#define FILEC(c) (((c) & 0x0F) == 0x02) +#define FILED(c) (((c) & 0x0F) == 0x03) +#define FILEE(c) (((c) & 0x0F) == 0x04) +#define FILEF(c) (((c) & 0x0F) == 0x05) +#define FILEG(c) (((c) & 0x0F) == 0x06) +#define FILEH(c) (((c) & 0x0F) == 0x07) +#define IS_WHITE_SQUARE_FR(f, r) (((f) + (r) - 1) & 1) +#define IS_WHITE_SQUARE_COOR(c) (IS_WHITE_SQUARE_FR(FILE(c), RANK(c))) +#define VALID_EP_SQUARE(c) (((c) == ILLEGAL_COOR) || ((c) == 0) || \ + (RANK3(c)) || \ + (RANK6(c))) + +// ---------------------------------------------------------------------- +// +// a move (4 bytes) = from/to, moved, captured, promoted and special +// +// 31 24 23 16 15 12 11 8 7 4 3 0 +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// | from | to | moved | capt | prom | flags | +// | | | | | +// | | | | | +// | | | | | +// | | +-------+-------+-- type and +// | | color of +// | | piece moved +// | | captured and +// | | promote targ +// +---------------+-- board location where +// move begins and ends +// +// +// Special flag asserted on special move types: +// +// if (special) +// { +// if (moved == PAWN) +// { +// if (promotion) +// { +// move is a promote (w/ or w/o capture) +// } +// else if (capture) +// { +// move is an en passant catpure +// } +// else +// { +// move is a double jump +// } +// } +// else if (moved == KING) +// { +// move is a castle (long or short) +// } +// else +// { +// invalid use of special flag +// } +// } +// +typedef union _MOVE +{ + ULONG uMove; + struct + { + UCHAR cFrom : 8; + UCHAR cTo : 8; + UCHAR pMoved : 4; + UCHAR pCaptured : 4; + UCHAR pPromoted : 4; + UCHAR bvFlags : 4; + }; +} MOVE; + +#define IS_SAME_MOVE(a, b) \ + (((a).uMove & 0x0FFFFFFF) == (((b).uMove & 0x0FFFFFFF))) + +#define MAKE_MOVE(from,to,piece,cap,prom,flags) \ + (((ULONG)(from)) | \ + ((ULONG)(to) << 8) | \ + ((ULONG)(piece) << 16) | \ + ((ULONG)(cap) << 20) | \ + ((ULONG)(prom) << 24) | \ + ((ULONG)(flags) << 28)) + +#define MAKE_MOVE_WITH_NO_PROM_OR_FLAGS(from,to,piece,cap) \ + (((ULONG)(from)) | \ + ((ULONG)(to) << 8) | \ + ((ULONG)(piece) << 16) | \ + ((ULONG)(cap) << 20)) + +// +// Move flag values: +// +#define MOVE_FLAG_SPECIAL (1) // en pass, prom, castle, double +#define IS_SPECIAL_MOVE(mv) \ + ((mv).uMove & 0x10000000) + +#define IS_CASTLE(mv) \ + (IS_SPECIAL_MOVE(mv) && IS_KING((mv).pMoved)) + +#ifdef DEBUG +#define IS_PROMOTION(mv) \ + (IS_SPECIAL_MOVE(mv) && ((mv).pPromoted)) +#else +#define IS_PROMOTION(mv) \ + ((mv).pPromoted) +#endif + +#define IS_CAPTURE_OR_PROMOTION(mv) \ + ((mv).uMove & 0x0FF00000) + +#define IS_ENPASSANT(mv) \ + (IS_SPECIAL_MOVE(mv) && (mv.pCaptured) && !IS_PROMOTION(mv)) + +#define IS_DOUBLE_JUMP(mv) \ + (IS_SPECIAL_MOVE(mv) && !IS_CAPTURE_OR_PROMOTION(mv)) + +#define MOVE_FLAG_KILLERMATE (2) // killer mate +#define IS_KILLERMATE_MOVE(mv) ((mv).uMove & 0x20000000) + +#define MOVE_FLAG_ESCAPING_CHECK (4) // escaping check +#define IS_ESCAPING_CHECK(mv) ((mv).uMove & 0x40000000) + +#define MOVE_FLAG_CHECKING (8) // checking move +#define IS_CHECKING_MOVE(mv) ((mv).uMove & 0x80000000) + +// ---------------------------------------------------------------------- +// +// Move list +// +#define MAX_MOVE_LIST (MAX_MOVES_PER_GAME + MAX_PLY_PER_SEARCH) + +// ---------------------------------------------------------------------- + +#pragma pack(1) +typedef union _ATTACK_BITV +{ + ULONG uWholeThing; + struct + { + union + { + UCHAR uSmall; + struct + { + UCHAR uNumAttacks : 3; // 0..2 + UCHAR uKing : 1; // 4..7 + UCHAR uQueen : 1; + UCHAR uRook : 1; + UCHAR uMinor : 1; + UCHAR uPawn : 1; + } small; + }; + + // -------------------- + union + { + USHORT uBig; + struct + { + USHORT uKing : 1; // 8..23 + USHORT uQueens : 4; + USHORT uRooks : 4; + USHORT uMinors : 4; + USHORT uPawns : 2; + USHORT uUnusedFlag1 : 1; + } big; + }; + + // ------------------- + union + { + UCHAR uXray; + struct + { + UCHAR uNumXrays : 3; + UCHAR uUnusedFlag2 : 1; + UCHAR uQueen : 1; // 24..28 + UCHAR uRook : 1; + UCHAR uBishop : 1; + UCHAR uUnusedFlag3 : 1; + } xray; + }; + }; +} +ATTACK_BITV; + +#define UNSAFE_FOR_MINOR(x) ((ULONG)((x).uWholeThing) & 0x00000080UL) +#define UNSAFE_FOR_ROOK(x) ((ULONG)((x).uWholeThing) & 0x000000C0UL) +#define UNSAFE_FOR_QUEEN(x) ((ULONG)((x).uWholeThing) & 0x000000E0UL) + +#define PAWN_BIT 0x00000080UL +#define MINOR_BIT 0x00000040UL +#define MINOR_XRAY_BIT 0x40000000UL +#define ROOK_BIT 0x00000020UL +#define ROOK_XRAY_BIT 0x20000000UL +#define QUEEN_BIT 0x00000010UL +#define QUEEN_XRAY_BIT 0x10000000UL + +#define INVALID_PIECE_INDEX (17) +#define IS_VALID_PIECE_INDEX(x) ((x) < INVALID_PIECE_INDEX) + +typedef union _SQUARE +{ + struct + { + PIECE pPiece; + ULONG uIndex; + }; + ATTACK_BITV bvAttacks[2]; +} +SQUARE; +#pragma pack() + +// +// POSITION +// +typedef struct _POSITION +{ + SQUARE rgSquare[128]; // where the pieces are, + // also, the attack table + UINT64 u64NonPawnSig; // hash signature + UINT64 u64PawnSig; // pawn hash signature + ULONG uToMove; // whose turn? + ULONG uFifty; // 50 moves w/o progress = draw + FLAG fCastled[2]; // record when sides have castled + BITV bvCastleInfo; // who can castle how? + COOR cEpSquare; // en-passant capture square + + COOR cPawns[2][8]; // location of pawns on the board + ULONG uPawnMaterial[2]; // pawn material of each side + ULONG uPawnCount[2]; // number of pawns for each side + + COOR cNonPawns[2][16]; // location of pieces on the board + ULONG uNonPawnMaterial[2]; // piece material of each side + ULONG uNonPawnCount[2][8]; // number of non-pawns / type + // 0 and 1 are the sum, + // 2..6 are per PIECE_TYPE + + ULONG uWhiteSqBishopCount[2]; // num bishops on white squares + SCORE iMaterialBalance[2]; // material balance + + // temporary storage space for use in eval + COOR cTrapped[2]; + ULONG uArmyScaler[2]; + ULONG uClosedScaler; + SCORE iScore[2]; + SCORE iReducedMaterialDownScaler[2]; + SCORE iTempScore; + ULONG uMinMobility[2]; + COOR cPiece; + ULONG uMinorsAtHome[2]; + BITBOARD bb; + ULONG uPiecesPointingAtKing[2]; +} +POSITION; + +// +// Castling permission bitvector flags. +// +#define CASTLE_WHITE_SHORT (1) +#define CASTLE_WHITE_LONG (2) +#define WHITE_CAN_CASTLE \ + (CASTLE_WHITE_SHORT | CASTLE_WHITE_LONG) +#define CASTLE_BLACK_SHORT (4) +#define CASTLE_BLACK_LONG (8) +#define BLACK_CAN_CASTLE \ + (CASTLE_BLACK_SHORT | CASTLE_BLACK_LONG) +#define CASTLE_NONE_POSSIBLE (0) +#define CASTLE_ALL_POSSIBLE \ + (WHITE_CAN_CASTLE | BLACK_CAN_CASTLE) + +// ---------------------------------------------------------------------- +// +// Move stack +// +#define MAX_MOVE_STACK (MAX_PLY_PER_SEARCH * \ + MAX_MOVES_PER_PLY) + +// +// Main part of the move stack, triads of moves, their values and flags +// that denote where the values came from +// +#define MVF_MOVE_SEARCHED (1) +#define MVF_EXTEND_MOVE (2) +#define MVF_REDUCE_MOVE (4) +#define MVF_PRUNE_SUBTREE (8) + +typedef struct _MOVE_STACK_MOVE_VALUE_FLAGS +{ + SCORE iValue; + MOVE mv; + BITV bvFlags; +} +MOVE_STACK_MOVE_VALUE_FLAGS; + +typedef struct _KEY_POINTER +{ + int iPointer; + ULONG uKey; +} +KEY_POINTER; + +typedef union _GENERATOR_FLAGS +{ + struct { + UCHAR uMoveCount; + UCHAR uKingMoveCount; + UCHAR uCheckingPieces; + UCHAR uUnused; + }; + ULONG uAllGenFlags; +} +GENERATOR_FLAGS; + +// +// A move stack +// +typedef struct _MOVE_STACK +{ +#ifdef DEBUG + POSITION board[MAX_PLY_PER_SEARCH]; +#endif + // + // Unblocked squares map, used for check detection + // + ULONG uUnblockedKeyValue[MAX_PLY_PER_SEARCH]; + KEY_POINTER sUnblocked[MAX_PLY_PER_SEARCH][128]; + + // + // The main move list, a long series of moves, their values and some + // flag bits to tell search what the values are based upon. + // + MOVE_STACK_MOVE_VALUE_FLAGS mvf[MAX_MOVE_STACK]; + + // + // uBegin[ply] and uEnd[ply] specify the start and end of moves gen- + // erated for a position at ply distance from the root. + // + ULONG uPly; + ULONG uBegin[MAX_PLY_PER_SEARCH]; + ULONG uEnd[MAX_PLY_PER_SEARCH]; + MOVE mvHash[MAX_PLY_PER_SEARCH]; + GENERATOR_FLAGS sGenFlags[MAX_PLY_PER_SEARCH]; +} +MOVE_STACK; + +#define GENERATE_NO_MOVES \ + ctx->sMoveStack.uEnd[ctx->uPly] = \ + ctx->sMoveStack.uBegin[ctx->uPly] + 1; \ + ctx->sMoveStack.uBegin[ctx->uPly + 1] = \ + ctx->sMoveStack.uEnd[ctx->uPly] + +#define GENERATE_ALL_MOVES (1) +#define GENERATE_ESCAPES (2) +#define GENERATE_CAPTURES_PROMS_CHECKS (3) +#define GENERATE_CAPTURES_PROMS (4) +#define GENERATE_DONT_SCORE (5) +#ifdef TEST +#define GENERATE_ALL_MOVES_CHECK_OK (6) +#endif + +#define MOVE_COUNT(ctx, x) \ + (((ctx)->sMoveStack.uEnd[(x)]) - (ctx)->sMoveStack.uBegin[(x)]) +#define ONE_LEGAL_MOVE(ctx, x) \ + (MOVE_COUNT(ctx, x) == 1) +#define NUM_KING_MOVES(ctx, x) \ + ((ctx)->sMoveStack.sGenFlags[(x)].uKingMoveCount) +#define NUM_CHECKING_PIECES(ctx, x) \ + ((ctx)->sMoveStack.sGenFlags[(x)].uCheckingPieces) + + +// ---------------------------------------------------------------------- +// +// Accumulators +// +typedef struct _COUNTERS +{ + struct + { + UINT64 u64Probes; + UINT64 u64OverallHits; + UINT64 u64UsefulHits; + UINT64 u64UpperBoundHits; + UINT64 u64LowerBoundHits; + UINT64 u64ExactScoreHits; + } + hash; + + struct + { + UINT64 u64Probes; + UINT64 u64Hits; + } + pawnhash; + + struct + { + UINT64 u64TotalNodeCount; + UINT64 u64QNodeCount; + UINT64 u64LeafCount; + UINT64 u64TerminalPositionCount; + UINT64 u64BetaCutoffs; + UINT64 u64BetaCutoffsOnFirstMove; + UINT64 u64NullMoves; + UINT64 u64NullMoveSuccess; +#ifdef TEST_NULL + UINT64 u64QuickNullSuccess; + UINT64 u64QuickNullDeferredSuccess; + UINT64 u64QuickNullFailures; + UINT64 u64AvoidNullSuccess; + UINT64 u64AvoidNullFailures; +#endif + UINT64 u64EvalHashHits; + UINT64 u64LazyEvals; + UINT64 u64FullEvals; + UINT64 u64CyclesInEval; + } + tree; + + struct + { + ULONG uNumSplits; + ULONG uNumSplitsTerminated; + } + parallel; + + struct + { + ULONG uPawnPush; + ULONG uCheck; + ULONG uMateThreat; + ULONG uRecapture; + ULONG uOneLegalMove; + ULONG uNoLegalKingMoves; + ULONG uMultiCheck; + ULONG uSingularMove; + ULONG uZugzwang; + ULONG uSingularReplyToCheck; + ULONG uEndgame; + ULONG uBotvinnikMarkoff; + ULONG uQExtend; + } + extension; + + struct + { + ULONG uProbes; + ULONG uHits; + } + egtb; +} +COUNTERS; + +typedef struct _CUMULATIVE_SEARCH_FLAGS +{ + // search + ULONG uNumChecks[2]; // not used + FLAG fInSuspiciousBranch; // not used + FLAG fInReducedDepthBranch; // not used + FLAG fAvoidNullmove; // restore + FLAG fVerifyNullmove; // restore + + // qsearch + ULONG uQsearchDepth; // restore + ULONG uQsearchNodes; // incremental + ULONG uQsearchCheckDepth; // restore + FLAG fCouldStandPat[2]; // restore +} +CUMULATIVE_SEARCH_FLAGS; + +// ---------------------------------------------------------------------- +// +// Searcher thread record +// +typedef struct _SPLIT_INFO +{ + // locks / counters + volatile ULONG uLock; // lock for this split node + volatile ULONG uNumThreadsHelping; // num threads in this node + volatile FLAG fTerminate; // signal helpers to terminate + + // moves in the split node + ULONG uRemainingMoves; // num moves remaining to do + ULONG uOnDeckMove; // next move to do + ULONG uNumMoves; + ULONG uAlreadyDone; + MOVE_STACK_MOVE_VALUE_FLAGS + mvf[MAX_MOVES_PER_PLY]; // the moves to search + + // input to the split node + POSITION sRootPosition; // the root position + MOVE mvPathToHere[MAX_PLY_PER_SEARCH]; // path from root to split + MOVE mvLast; // last move before split + ULONG uDepth; // remaining depth at split + INT iPositionExtend; // positional extension + SCORE iAlpha; // original alpha at split + SCORE iBeta; // beta at split + ULONG uSplitPositional; // pos->uPositional at split + CUMULATIVE_SEARCH_FLAGS sSearchFlags; // flags at split time + + // output from the split node + MOVE mvBest; // the best move + SCORE iBestScore; // it's score + COUNTERS sCounters; // updated counters + MOVE PV[MAX_PLY_PER_SEARCH]; + +#ifdef DEBUG + ULONG uSplitPly; + POSITION sSplitPosition; +#endif +} +SPLIT_INFO; + +typedef struct _PLY_INFO +{ +#ifdef DEBUG + POSITION sPosition; + SCORE iAlpha; + SCORE iBeta; +#endif + SCORE iEval; + INT iExtensionAmount; + FLAG fInCheck; + FLAG fInQsearch; + MOVE mv; + MOVE mvBest; + MOVE PV[MAX_PLY_PER_SEARCH]; + + SCORE iKingScore[2]; + ULONG uMinMobility[2]; + UINT64 u64NonPawnSig; + UINT64 u64PawnSig; + UINT64 u64Sig; + ULONG uFifty; + FLAG fCastled[2]; + ULONG uTotalNonPawns; + BITV bvCastleInfo; + COOR cEpSquare; +} +PLY_INFO; + +#define EVAL_HASH +#ifdef EVAL_HASH +#define EVAL_HASH_TABLE_SIZE (2097152) // 32Mb (per thread) +typedef struct _EVAL_HASH_ENTRY +{ + UINT64 u64Key; + SCORE iEval; + ULONG uPositional; + COOR cTrapped[2]; + +} EVAL_HASH_ENTRY; +#endif + +#define PAWN_HASH_TABLE_SIZE (131072) // 5.5Mb (per thread) +typedef struct _PAWN_HASH_ENTRY +{ + UINT64 u64Key; + BITBOARD bbPawnLocations[2]; + BITBOARD bbPasserLocations[2]; + BITBOARD bbStationaryPawns[2]; + SHORT iScore[2]; + UCHAR uCountPerFile[2][10]; + UCHAR uNumRammedPawns; + UCHAR uNumUnmovedPawns[2]; +} +PAWN_HASH_ENTRY; + +#define NUM_SPLIT_PTRS_IN_CONTEXT (8) + +typedef struct _SEARCHER_THREAD_CONTEXT +{ + ULONG uPly; // its distance from root + ULONG uPositional; // positional component of score + POSITION sPosition; // the board + MOVE_STACK sMoveStack; // the move stack + CUMULATIVE_SEARCH_FLAGS sSearchFlags; + PLY_INFO sPlyInfo[MAX_PLY_PER_SEARCH+1]; + MOVE mvKiller[MAX_PLY_PER_SEARCH][2]; + MOVE mvKillerEscapes[MAX_PLY_PER_SEARCH][2]; + MOVE mvNullmoveRefutations[MAX_PLY_PER_SEARCH]; + COUNTERS sCounters; + ULONG uThreadNumber; + SPLIT_INFO *pSplitInfo[NUM_SPLIT_PTRS_IN_CONTEXT]; + MOVE mvRootMove; + SCORE iRootScore; + ULONG uRootDepth; + PAWN_HASH_ENTRY rgPawnHash[PAWN_HASH_TABLE_SIZE]; +#ifdef EVAL_HASH + EVAL_HASH_ENTRY rgEvalHash[EVAL_HASH_TABLE_SIZE]; +#endif + CHAR szLastPV[SMALL_STRING_LEN_CHAR]; +} +SEARCHER_THREAD_CONTEXT; + +// +// When I added the pawn hash table and eval hash tables to searcher +// thread contexts they became too heavy to just allocate on the fly +// for things like checking the legality of SAN moves or seeing if an +// opening book line leads to a draw. This +// LIGHTWEIGHT_SEARCHER_CONTEXT structure can be cast into a full +// SEARCHER_THREAD_CONTEXT and passed safely into the Generate, +// MakeMove and UnMakeMove functions because they presently only +// need: +// +// 1. uPly +// 2. sPosition +// 3. sPlyInfo +// 4. sMoveStack +// +typedef struct _LIGHTWEIGHT_SEARCHER_CONTEXT +{ + ULONG uPly; + ULONG uPositional; + POSITION sPosition; + MOVE_STACK sMoveStack; + CUMULATIVE_SEARCH_FLAGS sSearchFlags; + PLY_INFO sPlyInfo[MAX_PLY_PER_SEARCH+1]; +} +LIGHTWEIGHT_SEARCHER_CONTEXT; + +// ---------------------------------------------------------------------- +// +// Global game options +// +typedef struct _GAME_OPTIONS +{ + ULONG uMyClock; + ULONG uOpponentsClock; + FLAG fGameIsRated; + FLAG fOpponentIsComputer; + ULONG uSecPerMove; + ULONG uMaxDepth; + UINT64 u64MaxNodeCount; + FLAG fShouldPonder; + FLAG fPondering; + FLAG fThinking; + FLAG fSuccessfulPonder; + MOVE mvPonder; + FLAG fShouldPost; + FLAG fForceDrawWorthZero; + ULONG uMyIncrement; + ULONG uMovesPerTimePeriod; + CHAR szAnalyzeProgressReport[SMALL_STRING_LEN_CHAR]; + FLAG fShouldAnnounceOpening; + SCORE iLastEvalScore; + UINT64 u64NodesSearched; + CHAR szLogfile[SMALL_STRING_LEN_CHAR]; + CHAR szEGTBPath[SMALL_STRING_LEN_CHAR]; + CHAR szBookName[SMALL_STRING_LEN_CHAR]; + ULONG uNumProcessors; + ULONG uNumHashTableEntries; + FLAG fNoInputThread; + FLAG fVerbosePosting; + FLAG fRunningUnderXboard; + FLAG fStatusLine; + FLAG fFastScript; + INT iResignThreshold; + + enum + { + CLOCK_NORMAL = 0, + CLOCK_FIXED, + CLOCK_INCREMENT, + CLOCK_NONE + } + eClock; + + enum + { + GAME_UNKNOWN = 0, + GAME_BULLET, + GAME_BLITZ, + GAME_STANDARD + } + eGameType; + + enum + { + I_PLAY_WHITE = 0, + I_PLAY_BLACK, + FORCE_MODE, + EDIT_MODE, + ANALYZE_MODE + } + ePlayMode; +} +GAME_OPTIONS; +extern GAME_OPTIONS g_Options; + +// ---------------------------------------------------------------------- +// +// Move timer +// + +#define TIMER_SEARCHING_FIRST_MOVE (0x1) +#define TIMER_SEARCHING_IMPORTANT_MOVE (0x2) +#define TIMER_RESOLVING_ROOT_FL (0x4) +#define TIMER_RESOLVING_ROOT_FH (0x8) +#define TIMER_JUST_OUT_OF_BOOK (0x10) +#define TIMER_CURRENT_OBVIOUS (0x20) +#define TIMER_CURRENT_WONT_UNBLOCK (0x40) +#define TIMER_ROOT_POSITION_CRITICAL (0x80) +#define TIMER_MOVE_IMMEDIATELY (0x100) +#define TIMER_MANY_ROOT_FLS (0x200) +#define TIMER_STOPPING (0x400) +#define TIMER_SPLIT_FAILED (0x800) + +typedef struct _MOVE_TIMER +{ + double dStartTime; + double dEndTime; + double dSoftTimeLimit; + double dHardTimeLimit; + ULONG uNodeCheckMask; + volatile BITV bvFlags; +} +MOVE_TIMER; + +// ---------------------------------------------------------------------- +// +// Special move tag literals +// +#define ILLEGALMOVE ((ULONG)0x1DDD8888) + +// +// useful macros +// +#ifdef DEBUG +void +_assert(CHAR *szFile, ULONG uLine); + +#define ASSERT(x) if (x) \ + { ; } \ + else \ + { _assert(__FILE__, __LINE__); } +#define VERIFY(x) ASSERT(x) +#else +#define ASSERT(x) ; +#define VERIFY(x) x; +#endif // DEBUG + +#ifdef PERF_COUNTERS +#define INC(x) ((x) += 1) +#else +#define INC(x) +#endif + +#define BREAKPOINT SystemDebugBreakpoint() + +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#ifdef _X86_ +// +// Note: MAXU, MINU and ABS_DIFF require arguments with the high order +// bit CLEAR to work right. +// +// These are branchless constructs. MAXU and MINU are equivalent to +// MIN and MAX (with the above restriction on inputs) +// +// MIN0 and MAX0 are equivalent to MAX(0, x) and MIN(0, x). These +// macros have no restiction on argument type. +// +// ABS_DIFF is equivalent to abs(x - y). Again, x and y must have +// their high-order bits CLEAR for this to work. +// +// Note: gcc generates code with cmovs so no need for MAXU/MINU on +// that compiler. +// +#define MINU(x, y) \ + (((((int)((x)-(y)))>>31) & ((x)-(y)))+(y)) +#define MAXU(x, y) \ + (((((int)((x)-(y)))>>31) & ((y)-(x)))+(x)) +#define MIN0(x) \ + ((x) & (((int)(x)) >> 31)) +#define MAX0(x) \ + ((x) & ~(((int)(x)) >> 31)) + + +#define ABS_DIFF(a, b) \ + (((b)-(a)) - ((((b) - (a)) & (((int)((b) - (a))) >> 31) ) << 1)) + +#endif // _X86_ + +#ifndef MINU +#define MINU(x, y) (MIN((x), (y))) +#endif + +#ifndef MAXU +#define MAXU(x, y) (MAX((x), (y))) +#endif + +#ifndef MIN0 +#define MIN0(x) (MIN((x), 0)) +#endif + +#ifndef MAX0 +#define MAX0(x) (MAX((x), 0)) +#endif + +#ifndef ABS_DIFF +#define ABS_DIFF(a, b) (abs((a) - (b))) +#endif + +#define FILE_DISTANCE(a, b) (ABS_DIFF(FILE((a)), FILE((b)))) +#define RANK_DISTANCE(a, b) (ABS_DIFF(((a) & 0xF0), ((b) & 0xF0)) >> 4) +#define REAL_DISTANCE(a, b) (MAXU(FILE_DISTANCE((a), (b)), \ + RANK_DISTANCE((a), (b)))) +#ifdef DEBUG +#define DISTANCE(a, b) DistanceBetweenSquares((a), (b)) +#else +#define DISTANCE(a, b) g_pDistance[(a) - (b)] +#endif // DEBUG + +#define IS_EMPTY( square ) (!(square)) +#define IS_OCCUPIED( square ) ((square)) + +#define IS_DEAD( listindex ) ((listindex) > 119) +#define IS_ALIVE( listindex ) ((listindex) <= 119) +#define ILLEGAL_COOR (0x88) +#define EDGE_DISTANCE(c) (MIN(MIN(abs(RANK(c) - 7), RANK(c)), \ + MIN(abs(FILE(c) - 7), FILE(c)))) +#define NOT_ON_EDGE(c) ((((c) & 0xF0) != 0x00) && \ + (((c) & 0xF0) != 0x70) && \ + (((c) & 0x0F) != 0x00) && \ + (((c) & 0x0F) != 0x07)) +#define ON_EDGE(c) (RANK8(c) || \ + RANK1(c) || \ + FILEA(c) || \ + FILEH(c)) +#define CORNER_DISTANCE(c) (MAX(MIN((ULONG)abs(RANK(c) - 7), RANK(c)),\ + MIN((ULONG)abs(FILE(c) - 7), FILE(c)))) +#define IN_CORNER(c) (((c) == A8) || \ + ((c) == A1) || \ + ((c) == H8) || \ + ((c) == H1)) +#define WHITE_CORNER_DISTANCE(c) (MIN(DISTANCE((c), A8), \ + DISTANCE((c), H1))) +#define BLACK_CORNER_DISTANCE(c) (MIN(DISTANCE((c), H8), \ + DISTANCE((c), A1))) +#define SYM_SQ(c) ((7 - (((c) & 0xF0) >> 4)) << 4) \ + | (7 - ((c) & 0x0F)) +#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a[0]))) +#define MAKE_PSQT(a, b, c, d) (((a) << 24) | ((b) << 16) | \ + ((c) << 8) | (d)) +#define TO64(x) ((x) & 0x7) + ((0x7 - ((x)>>4)) << 3) +#define COOR_TO_BIT_NUMBER(c) (((((c) & 0x70) >> 1) | ((c) & 0x7))) +#define SLOWCOOR_TO_BB(c) (1ULL << COOR_TO_BIT_NUMBER(c)) +#define COOR_TO_BB(c) (BBSQUARE[COOR_TO_BIT_NUMBER(c)]) +#define SLOW_BIT_NUMBER_TO_COOR(b) ((((b) / 8) << 4) + ((b) & 7)) +#define BIT_NUMBER_TO_COOR(b) ((((b) & 0xF8) << 1) | ((b) & 7)) + +#define BBRANK88 \ + SLOWCOOR_TO_BB(A8) | SLOWCOOR_TO_BB(B8) | SLOWCOOR_TO_BB(C8) | \ + SLOWCOOR_TO_BB(D8) | SLOWCOOR_TO_BB(E8) | SLOWCOOR_TO_BB(F8) | \ + SLOWCOOR_TO_BB(G8) | SLOWCOOR_TO_BB(H8) + +#define BBRANK77 \ + SLOWCOOR_TO_BB(A7) | SLOWCOOR_TO_BB(B7) | SLOWCOOR_TO_BB(C7) | \ + SLOWCOOR_TO_BB(D7) | SLOWCOOR_TO_BB(E7) | SLOWCOOR_TO_BB(F7) | \ + SLOWCOOR_TO_BB(G7) | SLOWCOOR_TO_BB(H7) + +#define BBRANK66 \ + SLOWCOOR_TO_BB(A6) | SLOWCOOR_TO_BB(B6) | SLOWCOOR_TO_BB(C6) | \ + SLOWCOOR_TO_BB(D6) | SLOWCOOR_TO_BB(E6) | SLOWCOOR_TO_BB(F6) | \ + SLOWCOOR_TO_BB(G6) | SLOWCOOR_TO_BB(H6) + +#define BBRANK55 \ + SLOWCOOR_TO_BB(A5) | SLOWCOOR_TO_BB(B5) | SLOWCOOR_TO_BB(C5) | \ + SLOWCOOR_TO_BB(D5) | SLOWCOOR_TO_BB(E5) | SLOWCOOR_TO_BB(F5) | \ + SLOWCOOR_TO_BB(G5) | SLOWCOOR_TO_BB(H5) + +#define BBRANK44 \ + SLOWCOOR_TO_BB(A4) | SLOWCOOR_TO_BB(B4) | SLOWCOOR_TO_BB(C4) | \ + SLOWCOOR_TO_BB(D4) | SLOWCOOR_TO_BB(E4) | SLOWCOOR_TO_BB(F4) | \ + SLOWCOOR_TO_BB(G4) | SLOWCOOR_TO_BB(H4) + +#define BBRANK33 \ + SLOWCOOR_TO_BB(A3) | SLOWCOOR_TO_BB(B3) | SLOWCOOR_TO_BB(C3) | \ + SLOWCOOR_TO_BB(D3) | SLOWCOOR_TO_BB(E3) | SLOWCOOR_TO_BB(F3) | \ + SLOWCOOR_TO_BB(G3) | SLOWCOOR_TO_BB(H3) + +#define BBRANK22 \ + SLOWCOOR_TO_BB(A2) | SLOWCOOR_TO_BB(B2) | SLOWCOOR_TO_BB(C2) | \ + SLOWCOOR_TO_BB(D2) | SLOWCOOR_TO_BB(E2) | SLOWCOOR_TO_BB(F2) | \ + SLOWCOOR_TO_BB(G2) | SLOWCOOR_TO_BB(H2) + +#define BBRANK11 \ + SLOWCOOR_TO_BB(A1) | SLOWCOOR_TO_BB(B1) | SLOWCOOR_TO_BB(C1) | \ + SLOWCOOR_TO_BB(D1) | SLOWCOOR_TO_BB(E1) | SLOWCOOR_TO_BB(F1) | \ + SLOWCOOR_TO_BB(G1) | SLOWCOOR_TO_BB(H1) + +#define BBFILEA \ + SLOWCOOR_TO_BB(A1) | SLOWCOOR_TO_BB(A2) | SLOWCOOR_TO_BB(A3) | \ + SLOWCOOR_TO_BB(A4) | SLOWCOOR_TO_BB(A5) | SLOWCOOR_TO_BB(A6) | \ + SLOWCOOR_TO_BB(A7) | SLOWCOOR_TO_BB(A8) + +#define BBFILEB \ + SLOWCOOR_TO_BB(B1) | SLOWCOOR_TO_BB(B2) | SLOWCOOR_TO_BB(B3) | \ + SLOWCOOR_TO_BB(B4) | SLOWCOOR_TO_BB(B5) | SLOWCOOR_TO_BB(B6) | \ + SLOWCOOR_TO_BB(B7) | SLOWCOOR_TO_BB(B8) + +#define BBFILEC \ + SLOWCOOR_TO_BB(C1) | SLOWCOOR_TO_BB(C2) | SLOWCOOR_TO_BB(C3) | \ + SLOWCOOR_TO_BB(C4) | SLOWCOOR_TO_BB(C5) | SLOWCOOR_TO_BB(C6) | \ + SLOWCOOR_TO_BB(C7) | SLOWCOOR_TO_BB(C8) + +#define BBFILED \ + SLOWCOOR_TO_BB(D1) | SLOWCOOR_TO_BB(D2) | SLOWCOOR_TO_BB(D3) | \ + SLOWCOOR_TO_BB(D4) | SLOWCOOR_TO_BB(D5) | SLOWCOOR_TO_BB(D6) | \ + SLOWCOOR_TO_BB(D7) | SLOWCOOR_TO_BB(D8) + +#define BBFILEE \ + SLOWCOOR_TO_BB(E1) | SLOWCOOR_TO_BB(E2) | SLOWCOOR_TO_BB(E3) | \ + SLOWCOOR_TO_BB(E4) | SLOWCOOR_TO_BB(E5) | SLOWCOOR_TO_BB(E6) | \ + SLOWCOOR_TO_BB(E7) | SLOWCOOR_TO_BB(E8) + +#define BBFILEF \ + SLOWCOOR_TO_BB(F1) | SLOWCOOR_TO_BB(F2) | SLOWCOOR_TO_BB(F3) | \ + SLOWCOOR_TO_BB(F4) | SLOWCOOR_TO_BB(F5) | SLOWCOOR_TO_BB(F6) | \ + SLOWCOOR_TO_BB(F7) | SLOWCOOR_TO_BB(F8) + +#define BBFILEG \ + SLOWCOOR_TO_BB(G1) | SLOWCOOR_TO_BB(G2) | SLOWCOOR_TO_BB(G3) | \ + SLOWCOOR_TO_BB(G4) | SLOWCOOR_TO_BB(G5) | SLOWCOOR_TO_BB(G6) | \ + SLOWCOOR_TO_BB(G7) | SLOWCOOR_TO_BB(G8) + +#define BBFILEH \ + SLOWCOOR_TO_BB(H1) | SLOWCOOR_TO_BB(H2) | SLOWCOOR_TO_BB(H3) | \ + SLOWCOOR_TO_BB(H4) | SLOWCOOR_TO_BB(H5) | SLOWCOOR_TO_BB(H6) | \ + SLOWCOOR_TO_BB(H7) | SLOWCOOR_TO_BB(H8) + +#define BBRANK72 \ + BBRANK77 | BBRANK66 | BBRANK55 | BBRANK44 | BBRANK33 | BBRANK22 + +#define BBRANK62 \ + BBRANK66 | BBRANK55 | BBRANK44 | BBRANK33 | BBRANK22 + +#define BBRANK52 \ + BBRANK55 | BBRANK44 | BBRANK33 | BBRANK22 + +#define BBRANK42 \ + BBRANK44 | BBRANK33 | BBRANK22 + +#define BBRANK32 \ + BBRANK33 | BBRANK22 + +#define BBRANK27 \ + BBRANK22 | BBRANK33 | BBRANK44 | BBRANK55 | BBRANK66 | BBRANK77 + +#define BBRANK37 \ + BBRANK33 | BBRANK44 | BBRANK55 | BBRANK66 | BBRANK77 + +#define BBRANK47 \ + BBRANK44 | BBRANK55 | BBRANK66 | BBRANK77 + +#define BBRANK57 \ + BBRANK55 | BBRANK66 | BBRANK77 + +#define BBRANK67 \ + BBRANK66 | BBRANK77 + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +// +// util.c +// +COMMAND(LearnPsqtFromPgn); + +COMMAND(GeneratePositionAndBestMoveSuite); + +CHAR * +WalkPV(SEARCHER_THREAD_CONTEXT *ctx); + +CHAR * +ReadNextGameFromPgnFile(FILE *pf); + +COOR +DistanceBetweenSquares(COOR a, COOR b); + +void CDECL +Trace(CHAR *szMessage, ...); + +void CDECL +Log(CHAR *szMessage, ...); + +void CDECL +Bug(CHAR *szMessage, ...); + +char * +FindChunk(char *sz, ULONG uTargetChunk); + +FLAG +BufferIsZeroed(BYTE *p, ULONG u); + +char * +ColorToString(ULONG u); + +char * +CoorToString(COOR c); + +char * +ScoreToString(SCORE iScore); + +char * +TimeToString(double d); + +ULONG +AcquireSpinLock(volatile ULONG *pSpinlock); + +FLAG +TryAcquireSpinLock(volatile ULONG *pSpinlock); + +void +ReleaseSpinLock(volatile ULONG *pSpinLock); + +BYTE +Checksum(BYTE *p, ULONG uSize); + +FLAG +BackupFile(CHAR *szFile); + +void +UtilPrintPV(SEARCHER_THREAD_CONTEXT *ctx, + SCORE iAlpha, + SCORE iBeta, + SCORE iScore, + MOVE mv); + +#define CANNOT_INITIALIZE_SPLIT (1) +#define INCONSISTENT_POSITION (2) +#define UNEXPECTED_SYSTEM_CALL_FAILURE (3) +#define SHOULD_NOT_GET_HERE (4) +#define GOT_ILLEGAL_MOVE_WHILE_PONDERING (5) +#define CANNOT_OFFICIALLY_MAKE_MOVE (6) +#define DETECTED_INCORRECT_INITIALIZATION (7) +#define INCONSISTENT_STATE (8) +#define FATAL_ACCESS_DENIED (9) +#define TESTCASE_FAILURE (10) +#define INITIALIZATION_FAILURE (11) + +void +UtilPanic(ULONG uPanicCode, + POSITION *pos, + void *a1, + void *a2, + void *a3, + char *file, ULONG line); + + +// +// main.c +// +#define LOGFILE_NAME "typhoon.log" +extern FILE *g_pfLogfile; + +void +Banner(void); + +FLAG +PreGameReset(FLAG fResetBoard); + +// +// system dependent exports (see win32.c or fbsd.c) +// +typedef ULONG (THREAD_ENTRYPOINT)(ULONG); + +#ifdef DEBUG +ULONG +GetHeapMemoryUsage(void); +#endif + +void +SystemDebugBreakpoint(void); + +CHAR * +SystemStrDup(CHAR *p); + +double +SystemTimeStamp(void); + +FLAG +SystemDoesFileExist(CHAR *szFilename); + +void +SystemDeferExecution(ULONG uMs); + +void +SystemFreeMemory(void *pMem); + +void * +SystemAllocateMemory(ULONG dwSizeBytes); + +FLAG +SystemMakeMemoryReadOnly(void *pMemory, ULONG dwSizeBytes); + +FLAG +SystemMakeMemoryNoAccess(void *pMemory, ULONG dwSizeBytes); + +FLAG +SystemMakeMemoryReadWrite(void *pMemory, ULONG dwSizeBytes); + +FLAG +SystemDependentInitialization(void); + +UINT64 FASTCALL +SystemReadTimeStampCounter(void); + +// +// This routine _must_ implement a full memory fence -- it is used in +// util.c to implement spinlocks. +// +FLAG +SystemCreateThread(THREAD_ENTRYPOINT *pEntry, ULONG uParam, ULONG *puHandle); + +FLAG +SystemWaitForThreadToExit(ULONG uThreadHandle); + +FLAG +SystemGetThreadExitCode(ULONG uThreadHandle, ULONG *puCode); + +FLAG +SystemDeleteThread(ULONG uThreadHandle); + +CHAR * +SystemGetDateString(void); + +CHAR * +SystemGetTimeString(void); + +FLAG +SystemCopyFile(CHAR *szSource, CHAR *szDest); + +FLAG +SystemDeleteFile(CHAR *szFile); + +ULONG +SystemCreateLock(void); + +FLAG +SystemDeleteLock(ULONG u); + +FLAG +SystemBlockingWaitForLock(ULONG u); + +FLAG +SystemReleaseLock(ULONG u); + +ULONG +SystemCreateSemaphore(ULONG u); + +FLAG +SystemDeleteSemaphore(ULONG u); + +void +SystemReleaseSemaphoreResource(ULONG u); + +void +SystemObtainSemaphoreResource(ULONG u); + + +// +// fen.c +// +#define STARTING_POSITION_IN_FEN \ + "rnbqkbnr/pppppppp/--------/8/8/--------/PPPPPPPP/RNBQKBNR w KQkq - 0 1" + +FLAG +LooksLikeFen(char *szFen); + +char * +PositionToFen(POSITION *p); + +FLAG +FenToPosition(POSITION *p, char *szFen); + +// +// testfen.c +// +#ifdef TEST +void +TestFenCode(void); +#endif + +// +// piece.c +// +// INVERTED VALUE == (VALUE_QUEEN / VALUE_PIECE) * VALUE_PAWN; +#define VALUE_PAWN 100 +#define INVERT_PAWN 900 +#define VALUE_KNIGHT 300 +#define INVERT_KNIGHT 300 +#define VALUE_BISHOP 300 +#define INVERT_BISHOP 300 +#define VALUE_ROOK 500 +#define INVERT_ROOK 180 +#define VALUE_QUEEN 975 +#define INVERT_QUEEN 100 +#define VALUE_KING (INFINITY) +#define INVERT_KING 1 + +#define VALUE_FULL_ARMY (8 * VALUE_PAWN) + (2 * VALUE_KNIGHT) + \ + (2 * VALUE_BISHOP) + (2 * VALUE_ROOK) + \ + VALUE_QUEEN + VALUE_KING +#define VALUE_MAX_ARMY (9 * VALUE_QUEEN) + (2 * VALUE_KNIGHT) + \ + (2 * VALUE_BISHOP) + (2 * VALUE_ROOK) + \ + VALUE_KING + +typedef struct _PIECE_DATA +{ + ULONG uValue; + ULONG uValueOver100; + ULONG uInvertedValue; + CHAR *szName; +} PIECE_DATA; + +extern PIECE_DATA g_PieceData[8]; + +#define PIECE_VALUE_OVER_100(p) (g_PieceData[PIECE_TYPE(p)].uValueOver100) +extern ULONG +PieceValueOver100(PIECE p); + +#define PIECE_VALUE(p) (g_PieceData[PIECE_TYPE(p)].uValue) +extern ULONG +PieceValue(PIECE p); + +#define INVERTED_PIECE_VALUE(p) (g_PieceData[PIECE_TYPE(p)].uInvertedValue) +extern ULONG +PieceInvertedValue(PIECE p); + +CHAR * +PieceAbbrev(PIECE p); + +// +// board.c +// +FLAG +VerifyPositionConsistency(POSITION *pos, FLAG fContinueOnError); + +FLAG +PositionsAreEquivalent(POSITION *p1, POSITION *p2); + +CHAR * +DrawTextBoardFromPosition(POSITION *pos); + +void +DumpPosition(POSITION *pos); + +CHAR * +CastleInfoString(BITV bv); + +void +SetRootToInitialPosition(void); + +// +// move.c +// +void +SlidePiece(POSITION *pos, COOR cFrom, COOR cTo); + +PIECE +LiftPiece(POSITION *pos, COOR cSquare); + +void +PlacePiece(POSITION *pos, COOR cSquare, PIECE pPiece); + +FLAG +MakeMove(SEARCHER_THREAD_CONTEXT *ctx, + MOVE mv); + +void +UnmakeMove(SEARCHER_THREAD_CONTEXT *ctx, + MOVE mv); + +FLAG +MakeUserMove(SEARCHER_THREAD_CONTEXT *ctx, MOVE mvUser); + +void +DumpMove(ULONG u); + +// +// movesup.c +// +#define MOVE_TO_INDEX(mv) (((mv).uMove & 0xFFFF) + \ + (0x10000 * GET_COLOR(mv.pMoved))) + +COOR +FasterExposesCheck(POSITION *pos, + COOR cRemove, + COOR cLocation); + +COOR +ExposesCheck(POSITION *pos, + COOR cRemove, + COOR cLocation); + +COOR +ExposesCheckEp(POSITION *pos, + COOR cTest, + COOR cIgnore, + COOR cBlock, + COOR cKing); + +FLAG +IsAttacked(COOR cTest, POSITION *pos, ULONG uSide); + +FLAG +InCheck(POSITION *pos, ULONG uSide); + +FLAG +SanityCheckMove(POSITION *pos, MOVE mv); + +FLAG +LooksLikeFile(CHAR c); + +FLAG +LooksLikeRank(CHAR c); + +FLAG +LooksLikeCoor(CHAR *szData); + +CHAR * +StripMove(CHAR *szMove); + +ULONG +LooksLikeMove(CHAR *szData); + +void FASTCALL +SelectBestWithHistory(SEARCHER_THREAD_CONTEXT *ctx, ULONG u); + +void FASTCALL +SelectBestNoHistory(SEARCHER_THREAD_CONTEXT *ctx, ULONG u); + +void FASTCALL +SelectMoveAtRoot(SEARCHER_THREAD_CONTEXT *ctx, ULONG u); + +#define NOT_MOVE 0 +#define MOVE_ICS 1 +#define MOVE_SAN 2 + +COMMAND(PerftCommand); + + +// +// testmove.c +// +#ifdef TEST +void +TestLiftPlaceSlidePiece(void); + +void +TestExposesCheck(void); + +void +TestIsAttacked(void); + +void +TestMakeUnmakeMove(void); +#endif + +// +// generate.c +// +#define SORT_THESE_FIRST (0x40000000) +#define FIRST_KILLER (0x20000000) +#define SECOND_KILLER (0x10000000) +#define THIRD_KILLER (0x08000000) +#define FOURTH_KILLER (0x04000000) +#define GOOD_MOVE (0x02000000) +#define STRIP_OFF_FLAGS (0x00FFFFFF) + +extern const int g_iQKDeltas[9]; +extern const int g_iNDeltas[9]; +extern const int g_iBDeltas[5]; +extern const int g_iRDeltas[5]; + +void +GenerateMoves(SEARCHER_THREAD_CONTEXT *ctx, + MOVE mvOrderFirst, + ULONG uType); + +FLAG +WouldGiveCheck(IN SEARCHER_THREAD_CONTEXT *ctx, + IN MOVE mv); + +// +// testgenerate.c +// +#ifdef TEST + +void +PlyTest(SEARCHER_THREAD_CONTEXT *ctx, + ULONG uDepth, + FLAG fRootPositionInCheck); + +void +TestMoveGenerator(void); + +void +TestLegalMoveGenerator(void); + +#endif + +// +// sig.c +// +extern UINT64 g_u64SigSeeds[128][7][2]; +extern UINT64 g_u64PawnSigSeeds[128][2]; +extern UINT64 g_u64CastleSigSeeds[16]; +extern UINT64 g_u64EpSigSeeds[9]; + +void +InitializeSigSystem(void); + +UINT64 +ComputePawnSig(POSITION *pos); + +UINT64 +ComputeSig(POSITION *pos); + +// +// mersenne.c +// +void +seedMT(unsigned int seed); + +unsigned int +reloadMT(void); + +unsigned int +randomMT(void); + +// +// data.c +// +typedef struct _VECTOR_DELTA +{ + UCHAR iVector[2]; + signed char iDelta; + signed char iNegDelta; +} +VECTOR_DELTA; + +extern ULONG g_uDistance[256]; +extern ULONG *g_pDistance; +extern VECTOR_DELTA g_VectorDelta[256]; +extern VECTOR_DELTA *g_pVectorDelta; +extern CHAR g_SwapTable[14][32][32]; +extern SCORE _PSQT[14][128]; +extern ULONG g_uSearchSortLimits[]; +extern MOVE NULLMOVE; +extern MOVE HASHMOVE; +extern MOVE RECOGNMOVE; +extern MOVE DRAWMOVE; +extern MOVE MATEMOVE; +extern FLAG g_fIsWhiteSquare[128]; +extern BITBOARD BBFILE[8]; +extern BITBOARD BBRANK[9]; +extern BITBOARD BBWHITESQ; +extern BITBOARD BBBLACKSQ; +extern BITBOARD BBLEFTSIDE; +extern BITBOARD BBRIGHTSIDE; +extern BITBOARD BBSQUARE[64]; +extern BITBOARD BBROOK_PAWNS; +extern BITBOARD BBPRECEEDING_RANKS[8][2]; +extern BITBOARD BBADJACENT_FILES[8]; +extern BITBOARD BBADJACENT_RANKS[9]; + +void +InitializeWhiteSquaresTable(void); + +void +InitializeVectorDeltaTable(void); + +void +InitializeSwapTable(void); + +void +InitializeDistanceTable(void); + +void +InitializeSearchDepthArray(void); + +ULONG +GetSearchSortLimit(ULONG); + +#ifdef DEBUG +#define SEARCH_SORT_LIMIT(x) (GetSearchSortLimit((x))) +#else +#define SEARCH_SORT_LIMIT(x) (g_uSearchSortLimits[(x)]) +#endif + +#ifdef DEBUG +ULONG CheckVectorWithIndex(int i, ULONG uColor); +#define CHECK_VECTOR_WITH_INDEX(i, color) \ + CheckVectorWithIndex(i, color) + +int DirectionBetweenSquaresWithIndex(int i); +#define CHECK_DELTA_WITH_INDEX(i) \ + DirectionBetweenSquaresWithIndex(i) + +int DirectionBetweenSquaresFromTo(COOR, COOR); +#define DIRECTION_BETWEEN_SQUARES(from, to) \ + DirectionBetweenSquaresFromTo(from, to) + +int NegativeDirectionBetweenSquaresWithIndex(int i); +#define NEG_DELTA_WITH_INDEX(i) \ + NegativeDirectionBetweenSquaresWithIndex(i) + +FLAG IsSquareWhite(COOR c); +#define IS_SQUARE_WHITE(c) \ + IsSquareWhite(c) + +#else +#define CHECK_VECTOR_WITH_INDEX(i, color) \ + (g_pVectorDelta[(i)].iVector[(color)]) + +#define CHECK_DELTA_WITH_INDEX(i) \ + (g_pVectorDelta[(i)].iDelta) + +#define DIRECTION_BETWEEN_SQUARES(cFrom, cTo) \ + CHECK_DELTA_WITH_INDEX((int)(cFrom) - (int)(cTo)) + +#define NEG_DELTA_WITH_INDEX(i) \ + (g_pVectorDelta[(i)].iNegDelta) + +#define IS_SQUARE_WHITE(c) \ + (g_fIsWhiteSquare[(c)]) +#endif + +// +// san.c +// +MOVE +ParseMoveSan(CHAR *szInput, + POSITION *pos); + +CHAR * +MoveToSan(MOVE mv, POSITION *pos); + +// +// testsan.c +// +void +TestSan(void); + +// +// list.c +// +void +InitializeListHead(IN DLIST_ENTRY *pListHead); + +FLAG +IsListEmpty(IN DLIST_ENTRY *pListHead); + +FLAG +RemoveEntryList(IN DLIST_ENTRY *pEntry); + +DLIST_ENTRY * +RemoveHeadList(IN DLIST_ENTRY *pListHead); + +DLIST_ENTRY * +RemoveTailList(IN DLIST_ENTRY *pListHead); + +void +InsertTailList(IN DLIST_ENTRY *pListHead, + IN DLIST_ENTRY *pEntry); + +void +InsertHeadList(IN DLIST_ENTRY *pListHead, + IN DLIST_ENTRY *pEntry); + +// +// command.c +// +void +ParseUserInput(FLAG fSearching); + +FLAG +InitializeCommandSystem(void); + +void +CleanupCommandSystem(void); + +// +// input.c +// +void +InitInputSystemInBatchMode(void); + +ULONG +InitInputSystemWithDedicatedThread(void); + +void +PushNewInput(CHAR *buf); + +CHAR * +PeekNextInput(void); + +CHAR * +ReadNextInput(void); + +CHAR * +BlockingReadInput(void); + +ULONG +NumberOfPendingInputEvents(void); + +volatile extern FLAG g_fExitProgram; + +// +// ics.c +// +MOVE +ParseMoveIcs(CHAR *szInput, POSITION *pos); + +CHAR * +MoveToIcs(MOVE mv); + +// +// testics.c +// +void +TestIcs(void); + +// +// gamelist.c +// +typedef enum _ERESULT +{ + RESULT_BLACK_WON = -1, + RESULT_DRAW = 0, + RESULT_WHITE_WON = 1, + RESULT_IN_PROGRESS, + RESULT_ABANDONED, + RESULT_UNKNOWN +} ERESULT; + +typedef struct _GAME_RESULT +{ + ERESULT eResult; + CHAR szDescription[256]; +} GAME_RESULT; + +typedef struct _GAME_PLAYER +{ + CHAR *szName; + CHAR *szDescription; + FLAG fIsComputer; + ULONG uRating; +} +GAME_PLAYER; + +typedef struct _GAME_HEADER +{ + CHAR *szGameDescription; + CHAR *szLocation; + GAME_PLAYER sPlayer[2]; + FLAG fGameIsRated; + UINT64 u64OpeningSig; + GAME_RESULT result; + CHAR *szInitialFen; +} +GAME_HEADER; + +typedef struct _GAME_MOVE +{ + DLIST_ENTRY links; + ULONG uNumber; + MOVE mv; + CHAR *szComment; + CHAR *szDecoration; + CHAR *szMoveInSan; + CHAR *szMoveInIcs; + CHAR *szUndoPositionFen; + SCORE iMoveScore; + UINT64 u64PositionSigAfterMove; + UINT64 u64PositionSigBeforeMove; + volatile FLAG fInUse; +} +GAME_MOVE; + +typedef struct _GAME_DATA +{ + GAME_HEADER sHeader; + DLIST_ENTRY sMoveList; +} +GAME_DATA; + +extern GAME_DATA g_GameData; + +POSITION * +GetRootPosition(void); + +FLAG +SetRootPosition(CHAR *szFen); + +void +ResetGameList(void); + +ULONG +GetMoveNumber(ULONG uColor); + +void +SetGameResultAndDescription(GAME_RESULT result); + +GAME_RESULT +GetGameResult(void); + +void +SetMyName(void); + +void +SetOpponentsName(CHAR *sz); + +void +SetMyRating(ULONG u); + +void +SetOpponentsRating(ULONG u); + +void +DumpGameList(void); + +void +TellGamelistThatIPlayColor(ULONG u); + +void +DumpPgn(void); + +FLAG +LoadPgn(CHAR *szPgn); + +ULONG +CountOccurrancesOfSigInOfficialGameList(UINT64 u64Sig); + +FLAG +DoesSigAppearInOfficialGameList(UINT64 u64Sig); + +FLAG +OfficiallyTakebackMove(void); + +FLAG +OfficiallyMakeMove(MOVE mv, SCORE iMoveScore, FLAG fFast); + +GAME_MOVE * +GetNthOfficialMoveRecord(ULONG n); + +void +MakeStatusLine(void); + +FLAG +IsLegalDrawByRepetition(void); + +// +// script.c +// +COMMAND(ScriptCommand); + +COMMAND(SolutionCommand); + +COMMAND(AvoidCommand); + +COMMAND(IdCommand); + +void +PostMoveTestSuiteReport(SEARCHER_THREAD_CONTEXT *); + +FLAG +CheckTestSuiteMove(MOVE mv, SCORE iScore, ULONG uDepth); + +FLAG +WeAreRunningASuite(void); + + +// +// vars.c +// +COMMAND(SetCommand); + +// +// root.c +// +extern ULONG g_uSoftExtendLimit; +extern ULONG g_uHardExtendLimit; +extern volatile MOVE_TIMER g_MoveTimer; +extern ULONG g_uExtensionReduction[MAX_PLY_PER_SEARCH]; + +#ifdef PERF_COUNTERS +#define KEEP_TRACK_OF_FIRST_MOVE_FHs(x) \ + ctx->sCounters.tree.u64BetaCutoffs++; \ + if (x) \ + { \ + ctx->sCounters.tree.u64BetaCutoffsOnFirstMove++;\ + } +#else +#define KEEP_TRACK_OF_FIRST_MOVE_FHs(x) +#endif + +#define GAME_NOT_OVER 0 +#define GAME_WHITE_WON 1 +#define GAME_BLACK_WON 2 +#define GAME_DRAW_STALEMATE 3 +#define GAME_DRAW_REPETITION 4 +#define GAME_ONE_LEGAL_MOVE 5 +#define GAME_DRAW_FIFTY_MOVES_WO_PROGRESS 6 + +GAME_RESULT +Think(POSITION *pos); + +GAME_RESULT +Ponder(POSITION *pos); + +GAME_RESULT +Iterate(SEARCHER_THREAD_CONTEXT *ctx); + +void +SetMoveTimerForSearch(FLAG fSwitchOver, ULONG uColor); + +void +SetMoveTimerToThinkForever(void); + +void +ClearRootNodecountHash(void); + +// +// draw.c +// +FLAG +IsDraw(SEARCHER_THREAD_CONTEXT *ctx); + + +// +// search.c +// +#define QPLIES_OF_NON_CAPTURE_CHECKS (1) +#define FUTILITY_BASE_MARGIN (50) // + ctx->uPositional (min 100) +#define DO_IID +#define IID_R_FACTOR (TWO_PLY + HALF_PLY) + +#ifndef MP +#define WE_SHOULD_STOP_SEARCHING (g_MoveTimer.bvFlags & TIMER_STOPPING) +#else +#define WE_SHOULD_STOP_SEARCHING ((g_MoveTimer.bvFlags & TIMER_STOPPING) || \ + (ThreadUnderTerminatingSplit(ctx))) +#endif + +SCORE FASTCALL +QSearch(SEARCHER_THREAD_CONTEXT *ctx, + SCORE iAlpha, + SCORE iBeta); + +SCORE FASTCALL +Search(SEARCHER_THREAD_CONTEXT *ctx, + SCORE iAlpha, + SCORE iBeta, + ULONG uDepth); + + +// +// searchsup.c +// +SCORE +ComputeMoveScore(IN SEARCHER_THREAD_CONTEXT *ctx, + IN MOVE mv, + IN ULONG uMoveNum); + +FLAG +ThreadUnderTerminatingSplit(SEARCHER_THREAD_CONTEXT *); + +FLAG +WeShouldDoHistoryPruning(IN SCORE iRoughEval, + IN SCORE iAlpha, + IN SCORE iBeta, + IN SEARCHER_THREAD_CONTEXT *ctx, + IN ULONG uRemainingDepth, + IN ULONG uLegalMoves, + IN MOVE mv, + IN ULONG uMoveNum, + IN INT iExtend); + +FLAG +WeShouldTryNullmovePruning(IN SEARCHER_THREAD_CONTEXT *ctx, + IN SCORE iAlpha, + IN SCORE iBeta, + IN SCORE iRoughEval, + IN ULONG uNullDepth); + +FLAG +TryNullmovePruning(IN OUT SEARCHER_THREAD_CONTEXT *ctx, + IN OUT FLAG *pfThreat, + IN SCORE iAlpha, + IN SCORE iBeta, + IN ULONG uNullDepth, + IN OUT INT *piOrigExtend, + OUT SCORE *piNullScore); + +void +UpdatePV(SEARCHER_THREAD_CONTEXT *ctx, MOVE mv); + +FLAG +CheckInputAndTimers(IN SEARCHER_THREAD_CONTEXT *ctx); + +void +ComputeReactionToCheckExtension(IN OUT SEARCHER_THREAD_CONTEXT *ctx, + IN ULONG uGenFlags, + IN ULONG uMoveNum, + IN SCORE iRoughEval, + IN SCORE iAlpha, + IN OUT INT *piExtend, + IN OUT INT *piOrigExtend); + +void +ComputeMoveExtension(IN OUT SEARCHER_THREAD_CONTEXT *ctx, + IN SCORE iAlpha, + IN SCORE iBeta, + IN ULONG uMoveNum, + IN SCORE iRoughEval, + IN ULONG uDepth, + IN OUT INT *piExtend); + +SCORE +RescoreMovesViaSearch(IN SEARCHER_THREAD_CONTEXT *ctx, + IN ULONG uDepth, + IN SCORE iAlpha, + IN SCORE iBeta); + +FLAG +MateDistancePruningCutoff(IN ULONG uPly, + IN FLAG fInCheck, + IN OUT SCORE *piBestScore, + IN OUT SCORE *piAlpha, + IN OUT SCORE *piBeta); + +FLAG +CommonSearchInit(IN SEARCHER_THREAD_CONTEXT *ctx, + IN OUT SCORE *piAlpha, + IN OUT SCORE *piBeta, + IN OUT SCORE *piScore); + +ULONG +SelectNullmoveRFactor(IN SEARCHER_THREAD_CONTEXT *ctx, + IN INT uDepth); + +#define VERIFY_BEFORE (1) +#define VERIFY_AFTER (2) + +FLAG +SanityCheckMoves(IN SEARCHER_THREAD_CONTEXT *ctx, + IN ULONG uCurrent, + IN ULONG uType); + + +// +// testsearch.c +// +FLAG +TestSearch(void); + +// +// see.c +// +#define SEE_HEAPS + +SCORE +SEE(POSITION *pos, + MOVE mv); + +typedef struct _SEE_THREESOME +{ + PIECE pPiece; + COOR cLoc; + ULONG uVal; +} SEE_THREESOME; + +typedef struct _SEE_LIST +{ + ULONG uCount; + SEE_THREESOME data[16]; +} +SEE_LIST; + +SCORE +ControlsSquareMinusPiece(ULONG uSide, + POSITION *pos, + COOR c, + COOR cIgnore); + +// +// testsee.c +// +SCORE +DebugSEE(POSITION *pos, + MOVE mv); + +void +TestGetAttacks(void); + +// +// hash.c +// +#define NUM_HASH_ENTRIES_PER_LINE 4 +#define HASH_FLAG_EXACT 0x1 +#define HASH_FLAG_LOWER 0x2 +#define HASH_FLAG_UPPER 0x4 +#define HASH_FLAG_VALID_BOUNDS 0x7 +#define HASH_FLAG_THREAT 0x8 +#define HASH_FLAG_DIRTY 0xF0 + +typedef struct _HASH_ENTRY +{ + MOVE mv; // 0 1 2 3 + UCHAR uDepth; // 4 + UCHAR bvFlags; // 5 ==> d d d d | thr up low exact + signed short iValue; // 6 7 + UINT64 u64Sig; // 8 9 A B C D E F == 16 bytes +} HASH_ENTRY; + +FLAG +InitializeHashSystem(void); + +void +CleanupHashSystem(void); + +void +ClearHashTable(void); + +void +DirtyHashTable(void); + +void +StoreLowerBound(MOVE mvBestMove, + POSITION *pos, + SCORE iValue, + ULONG uDepth, + FLAG fThreat); +void +StoreExactScore(MOVE mvBestMove, + POSITION *pos, + SCORE iValue, + ULONG uDepth, + FLAG fThreat, + ULONG uPly); + +void +StoreUpperBound(//MOVE mvBestMove, + POSITION *pos, + SCORE iValue, + ULONG uDepth, + FLAG fThreat); + +HASH_ENTRY * +HashLookup(SEARCHER_THREAD_CONTEXT *ctx, + ULONG uDepth, + ULONG uNextDepth, + SCORE iAlpha, + SCORE iBeta, + FLAG *pfThreat, + FLAG *pfAvoidNull, + MOVE *pHashMove, + SCORE *piScore); + +COOR +CheckHashForDangerSquare(POSITION *pos); + +MOVE +GetPonderMove(POSITION *pos); + +extern ULONG g_uHashTableSizeEntries; +extern ULONG g_uHashTableSizeBytes; +extern HASH_ENTRY *g_pHashTable; + +// +// testhash.c +// +void +AnalyzeFullHashTable(void); + +// +// positionhash.c +// +// IDEA: store "mate threat" flag in here? +// IDEA: store "king safety" numbers in here? +// +typedef struct _POSITION_HASH_ENTRY { + UINT64 u64Sig; + UCHAR cEnprise[2]; + UCHAR uEnpriseCount[2]; + UCHAR cTrapped[2]; +} POSITION_HASH_ENTRY; + +void +InitializePositionHashSystem(void); + +void +CleanupPositionHashSystem(void); + +void +StoreEnprisePiece(POSITION *pos, COOR cSquare); + +void +StoreTrappedPiece(POSITION *pos, COOR cSquare); + +COOR +GetEnprisePiece(POSITION *pos, ULONG uSide); + +ULONG +GetEnpriseCount(POSITION *pos, ULONG uSide); + +COOR +GetTrappedPiece(POSITION *pos, ULONG uSide); + +FLAG +SideCanStandPat(POSITION *pos, ULONG uSide); + +ULONG +ValueOfMaterialInTroubleDespiteMove(POSITION *pos, ULONG uSide); + +ULONG +ValueOfMaterialInTroubleAfterNull(POSITION *pos, ULONG uSide); + +// +// pawnhash.c +// +#define COOR_TO_BIT(x) ((x) & 0x7) + ((0x7 - ((x) >> 4)) << 3) + +void +ClearPawnHashStats(void); + +void +ReportPawnHashStats(void); + +PAWN_HASH_ENTRY * +PawnHashLookup(SEARCHER_THREAD_CONTEXT *ctx); + +// +// eval.c +// +#define LAZY_EVAL +#define LAZE_EVAL_BASE_SCORE 10 +extern const int g_iAhead[2]; +extern const int g_iBehind[2]; + +ULONG +DNABufferSizeBytes(); + +char * +ExportEvalDNA(); + +FLAG +WriteEvalDNA(char *szFilename); + +FLAG +ImportEvalDNA(char *p); + +FLAG +ReadEvalDNA(char *szFilename); + + + +SCORE +Eval(SEARCHER_THREAD_CONTEXT *, SCORE, SCORE); + +FLAG +EvalPasserRaces(POSITION *, + PAWN_HASH_ENTRY *); + +ULONG +CountKingSafetyDefects(POSITION *pos, + ULONG uSide); + +// +// testeval.c +// +#ifdef EVAL_DUMP +void +TestEval(void); + +void +EvalTraceReport(void); + +void +EvalTrace(ULONG uColor, PIECE p, COOR c, SCORE iVal, CHAR *szMessage); + +SCORE +EvalSigmaForPiece(POSITION *pos, COOR c); + +void +EvalTraceClear(void); + +void +TestEvalWithSymmetry(void); + +#define EVAL_TERM(COL, PIE, COO, VAL, ADJ, MESS) \ + (VAL) += (ADJ); \ + EvalTrace((COL), (PIE), (COO), (ADJ), (MESS)); +#else +#define EVAL_TERM(COL, PIE, COO, VAL, ADJ, MESS) \ + (VAL) += (ADJ); +#endif + +// +// bitboard.c +// +void +InitializeBitboards(void); + +ULONG CDECL +SlowCountBits(BITBOARD bb); + +ULONG CDECL +DeBruijnFirstBit(BITBOARD bb); + +ULONG CDECL +SlowFirstBit(BITBOARD bb); + +ULONG CDECL +SlowLastBit(BITBOARD bb); + +#ifdef CROUTINES +#define CountBits SlowCountBits +#define FirstBit SlowFirstBit +#define LastBit SlowLastBit +#endif + +COOR +CoorFromBitBoardRank8ToRank1(BITBOARD *pbb); + +COOR +CoorFromBitBoardRank1ToRank8(BITBOARD *pbb); + +// +// x86.asm +// +ULONG CDECL +CountBits(BITBOARD bb); + +ULONG CDECL +FirstBit(BITBOARD bb); + +ULONG CDECL +LastBit(BITBOARD bb); + +ULONG CDECL +LockCompareExchange(volatile void *pDest, + ULONG uExch, + ULONG uComp); + +ULONG CDECL +LockIncrement(volatile void *pDest); + +ULONG CDECL +LockDecrement(volatile void *pDest); + +FLAG CDECL +CanUseParallelOpcodes(); + +ULONG CDECL +ParallelCompareUlong(ULONG uComparand, void *pComparators); + +ULONG CDECL +ParallelCompareVector(void *pComparand, void *pComparators); + +void CDECL +GetAttacks(SEE_LIST *pList, + POSITION *pos, + COOR cSquare, + ULONG uSide); + +void CDECL +SlowGetAttacks(SEE_LIST *pList, + POSITION *pos, + COOR cSquare, + ULONG uSide); +#ifdef CROUTINES +#define GetAttacks SlowGetAttacks +#endif + +#ifdef _X86_ +// +// Note: this is most of the stuff that x86.asm assumes about the +// internal data structures. If any of this fails then either the +// assembly language code needs to be updated or you need to use the C +// version of the routine in see.c instead. +// +#define ASSERT_ASM_ASSUMPTIONS \ + ASSERT(VALUE_PAWN == 100); \ + ASSERT(OFFSET_OF(uCount, SEE_LIST) == 0); \ + ASSERT(OFFSET_OF(data, SEE_LIST) == 4); \ + ASSERT(sizeof(SEE_THREESOME) == 12); \ + ASSERT(OFFSET_OF(pPiece, SEE_THREESOME) == 0); \ + ASSERT(OFFSET_OF(cLoc, SEE_THREESOME) == 4); \ + ASSERT(OFFSET_OF(uVal, SEE_THREESOME) == 8); \ + ASSERT(OFFSET_OF(cNonPawns, POSITION) == 0x478); \ + ASSERT(OFFSET_OF(uNonPawnCount, POSITION) == 0x500); \ + ASSERT(OFFSET_OF(rgSquare, POSITION) == 0); \ + ASSERT(sizeof(SQUARE) == 8); \ + ASSERT(sizeof(VECTOR_DELTA) == 4); \ + ASSERT(sizeof(g_VectorDelta) == 256 * 4); \ + ASSERT(OFFSET_OF(iVector, VECTOR_DELTA) == 0); \ + ASSERT(OFFSET_OF(iDelta, VECTOR_DELTA) == 2); \ + ASSERT(OFFSET_OF(iNegDelta, VECTOR_DELTA) == 3); \ + ASSERT(sizeof(g_PieceData) == 8 * 4 * 4); \ + ASSERT(OFFSET_OF(uValue, PIECE_DATA) == 0); +#else +#define ASSERT_ASM_ASSUMPTIONS +#endif + +// +// testbitboard.c +// +void +TestBitboards(void); + +// +// dynamic.c +// +extern ULONG g_HistoryCounters[14][128]; + +ULONG +GetMoveFailHighPercentage(MOVE mv); + +void +UpdateDynamicMoveOrdering(SEARCHER_THREAD_CONTEXT *ctx, + ULONG uRemainingDepth, + MOVE mvBest, + SCORE iScore, + ULONG uCurrent); + +void +NewKillerMove(SEARCHER_THREAD_CONTEXT *ctx, MOVE mv, SCORE iScore); + +FLAG +InitializeDynamicMoveOrdering(void); + +void +CleanupDynamicMoveOrdering(void); + +void +ClearDynamicMoveOrdering(void); + +void +MaintainDynamicMoveOrdering(void); + +void +IncrementMoveHistoryCounter(MOVE mv, ULONG u); + +void +DecrementMoveHistoryCounter(MOVE mv, ULONG u); + +// +// split.c +// +extern volatile ULONG g_uNumHelpersAvailable; +extern ULONG g_uNumHelperThreads; + +FLAG +InitializeParallelSearch(void); + +FLAG +CleanupParallelSearch(void); + +void +ClearHelperThreadIdleness(void); + +void +DumpHelperIdlenessReport(void); + +SCORE +StartParallelSearch(IN SEARCHER_THREAD_CONTEXT *ctx, + IN OUT SCORE *piAlpha, + IN SCORE iBeta, + IN OUT SCORE *piBestScore, + IN OUT MOVE *pmvBest, + IN ULONG uMoveNum, + IN INT iPositionExtend, + IN ULONG uDepth); + +void +InitializeSearcherContext(POSITION *pos, SEARCHER_THREAD_CONTEXT *ctx); + +void +ReInitializeSearcherContext(POSITION *pos, SEARCHER_THREAD_CONTEXT *ctx); + +void +InitializeLightweightSearcherContext(POSITION *pos, + LIGHTWEIGHT_SEARCHER_CONTEXT *ctx); + +// +// book.c +// + +#define BOOK_PROBE_MISS_LIMIT (7) +#define FLAG_DISABLED (1) +#define FLAG_ALWAYSPLAY (2) +#define FLAG_DELETED (4) + +#define BOOKMOVE_SELECT_MOVE (1) +#define BOOKMOVE_DUMP (2) + +#pragma pack(4) +typedef struct _BOOK_ENTRY +{ + UINT64 u64Sig; // 8 bytes + UINT64 u64NextSig; // 8 bytes + MOVE mvNext; // 4 bytes + ULONG uWins; // 4 bytes + ULONG uDraws; // 4 bytes + ULONG uLosses; // 4 bytes + BITV bvFlags; // 4 bytes +} +BOOK_ENTRY; +#pragma pack() + +typedef struct _OPENING_NAME_MAPPING +{ + UINT64 u64Sig; + CHAR *szString; +} +OPENING_NAME_MAPPING; + +#define BOOK_EDITING_RECORD "bkedit.edt" +#define OPENING_LEARNING_FILENAME "bklearn.bin" + +typedef struct _OPENING_LEARNING_ENTRY +{ + UINT64 u64Sig; + ULONG uWhiteWins; + ULONG uDraws; + ULONG uBlackWins; +} +OPENING_LEARNING_ENTRY; + +FLAG +InitializeOpeningBook(void); + +void +ResetOpeningBook(void); + +void +CleanupOpeningBook(void); + +MOVE +BookMove(POSITION *pos, + BITV bvFlags); + +COMMAND(BookCommand); + +extern ULONG g_uBookProbeFailures; +extern FLAG g_fTournamentMode; +extern CHAR *g_szBookName; + +// +// bench.c +// +COMMAND(BenchCommand); + +// +// testdraw.c +// +void +TestDraw(void); + +// +// probe.c +// +FLAG +ProbeEGTB(SEARCHER_THREAD_CONTEXT *ctx, SCORE *score); + +void +InitializeEGTB(void); + +void +CleanupEGTB(void); + +// +// dumptree.c +// +#ifdef DUMP_TREE + +void +InitializeTreeDump(void); + +void +CleanupTreeDump(void); + +void +DTEnterNode(SEARCHER_THREAD_CONTEXT *ctx, + ULONG uDepth, + FLAG fIsQNode, + SCORE iAlpha, + SCORE iBeta); + +void +DTLeaveNode(SEARCHER_THREAD_CONTEXT *ctx, + FLAG fQNode, + SCORE iBestScore, + MOVE mvBestMove); + +void CDECL +DTTrace(ULONG uPly, CHAR *szMessage, ...); + +#define DTTRACE(...) DTTrace(ctx->uPly, __VA_ARGS__) + +#else + +#define DTTRACE(...) + +#define DTEnterNode(...) + +#define DTLeaveNode(...) + +#define InitializeTreeDump(...) + +#define CleanupTreeDump(...) + +#endif + +// +// testsup.c +// +FLAG +IsBoardLegal(POSITION *pos); + +void +GenerateRandomLegalPosition(POSITION *pos); + +void +GenerateRandomLegalSymetricPosition(POSITION *pos); + +// +// recogn.c +// +#define UNRECOGNIZED (0) +#define RECOGN_EXACT (1) +#define RECOGN_UPPER (2) +#define RECOGN_LOWER (3) +#define RECOGN_EGTB (4) + +void +InitializeInteriorNodeRecognizers(void); + +ULONG +RecognLookup(SEARCHER_THREAD_CONTEXT *ctx, + SCORE *piScore, + FLAG fProbeEGTB); + +#ifdef EVAL_HASH +void +ClearEvalHashStats(void); + +void +ReportEvalHashStats(void); + +SCORE +ProbeEvalHash(SEARCHER_THREAD_CONTEXT *ctx); + +SCORE +GetRoughEvalScore(IN SEARCHER_THREAD_CONTEXT *ctx, + IN SCORE iAlpha, + IN SCORE iBeta, + IN FLAG fUseHash); + +void +StoreEvalHash(SEARCHER_THREAD_CONTEXT *ctx, SCORE iScore); +#endif // EVAL_HASH + +#endif // CHESS |
