#if LARGE_ETYPE typedef int etype; #if USE_STATIC_PAWN_VALUE #define STATIC_PAWN_VALUE 1000 #else #define STATIC_PAWN_VALUE 10000 #define PAWN_VALUE 10000 #endif #else typedef short etype; #define STATIC_PAWN_VALUE 100 #define PAWN_VALUE 100 #endif #include "eval.h" #define DEFAULT_HASH_TABLE_SIZE 8 /* in Mb */ #ifndef RAMP_FACTOR #define RAMP_FACTOR 1.0 #endif #define CRAFTY 1 #define KNIGHTCAP 2 #ifndef SHORT_GAME #define SHORT_GAME 10 #endif #define STORE_ONLY_NEGATIVE 0 #define USE_APPLET 0 #define SEARCH_OPENING_VARIATIONS 0 #define DUMPING_TD_UPDATES 1 #define NO_STALEMATE_LEARN 1 #define SEARCH_DEBUG 0 #define __COEFFS_PER_STAGE__ (__TOTAL_COEFFS__/(MATING+1)) #define USE_HASH_TABLES 1 #define USE_ETTC_HASH 1 #define USE_PAWN_DEEPENING 0 #define USE_CHECK_DEEPENING 1 #define USE_RECAPTURE_DEEPENING 1 #define USE_BEST_CAPTURE_DEEPENING 0 #define USE_HUNG_CAPTURE_DEEPENING 0 #define USE_SINGULAR_EXTENSION 1 #define USE_EVAL_TACTICS 1 #define USE_EGTB 1 #define USE_NULL_MOVE 1 #define USE_NULLMOVE_FIXUP 1 #define CONFIRM_NULL_MOVES 1 #define USE_OVERLOADED 1 #define USE_RAZORING 1 #define USE_ASYMMETRIC_RAZORING 0 #define USE_EVAL_SHORTCUT 1 #define USE_QUIESCE_SHORTCUT 0 #define USE_PESSIMISTIC_PRUNING 0 #define USE_ASYMMETRIC_EXTENSIONS 1 #define USE_ASYMMETRIC_EVAL 1 #define USE_ASYMMETRIC_NULLMOVE 1 #ifndef USE_SLIDING_CONTROL #define USE_SLIDING_CONTROL 1 #endif #define USE_FUTILITY 1 #define USE_FAST_QUIESCE 0 #define USE_PAWNPUSH_QUIESCE 0 #define REJECT_LOW_BRAIN_MOVES 0 #define TEST_QUIESCE 0 #define TEST_EVAL_SHORTCUT 0 #define TEST_NULL_MOVE 0 #define TEST_GRADIENT 0 #define TEST_MTD_FAST 0 #define SAVE_EXTENSIONS 0 #define FUTILE_THRESHOLD (1.3*STATIC_PAWN_VALUE) #define USE_INTERNAL_PRUNING 0 #define USE_HALF_PRUNING 0 #ifndef STORE_LEAF_POS #define STORE_LEAF_POS 0 #endif #ifndef USE_PBRAIN #define USE_PBRAIN 1 #endif #define BRAIN_FILE "brain.dat" #ifndef RESIGN_VALUE #define RESIGN_VALUE (ROOK_VALUE) #endif #define NULL_MOVE_PLY 3 #define PONDER_NULL_MOVE_PLY 3 #define MAX_EXTENSIONS 20 #define RAZOR_THRESHOLD (0.9*STATIC_PAWN_VALUE) #define MAX_MOVES_MULLED 3 #define NULL_MOVE_THRESHOLD 6 #define MTD_THRESHOLD (mulling?(0.01*STATIC_PAWN_VALUE):(0.07*STATIC_PAWN_VALUE)) #define MTD_DELTA (0.05*STATIC_PAWN_VALUE) #define MAX_CELLS 64 #define TIMER_NODES 1000 #define CAPTURE_SEARCH_DEPTH 0 #define USE_FORWARD_PRUNING 0 #define PRUNE_THRESHOLD (STATIC_PAWN_VALUE/4) #define PAR_SPLIT_LEVEL 1 #define TREE_PRINT_PLY 0 #define MAX_DEPTH 50 #define WALL_CLOCK 1 #define HASH_LEVELS 2 #define HASH_MISS 0 #define HASH_HIT 1 #define HASH_AVOID_NULL 2 /* number of moves to buffer before writing gradients to disk */ #define BUFFERED_MOVES 10 #define GRAD_TEMP_SIZE (BUFFERED_MOVES*__TOTAL_COEFFS__) #define NUM_SQUARES (8*8) #define MAX_MOVES (306) /* the maximum number of moves that can be made in one move - probably a gross overestimate */ #ifndef MAX_GAME_MOVES #define MAX_GAME_MOVES 1000 /* the players should give up by then :-) */ #endif #define PIECE_NONE 0 #define PIECE_WHITE 1 #define PIECE_BLACK -1 #define IKING 0 #define IQUEEN 1 #define IKROOK 2 #define IQROOK 3 #define IKBISHOP 4 #define IQBISHOP 5 #define IKKNIGHT 6 #define IQKNIGHT 7 #define IQRPAWN 8 #define IQNPAWN 9 #define IQBPAWN 10 #define IQPAWN 11 #define IKPAWN 12 #define IKBPAWN 13 #define IKNPAWN 14 #define IKRPAWN 15 #define FPAWN 0 #define GPAWN 1 #define HPAWN 2 #define HGPAWN 3 #define GHPAWN 4 #define FGPAWN 5 #define APAWN 6 #define BPAWN 7 #define CPAWN 8 #define ABPAWN 9 #define BAPAWN 10 #define CBPAWN 11 #define WHITE_MASK (0x0000FFFF) #define BLACK_MASK (0xFFFF0000) #define WKING_MASK (0x00000001) #define BKING_MASK (0x00010000) #define KING_MASK (0x00010001) #define WQUEEN_MASK (0x00000002) #define BQUEEN_MASK (0x00020000) #define QUEEN_MASK (0x00020002) #define WROOK_MASK (0x0000000C) #define WKROOK_MASK (0x00000004) #define WQROOK_MASK (0x00000008) #define WBISHOP_MASK (0x00000030) #define WKBISHOP_MASK (0x00000010) #define WQBISHOP_MASK (0x00000020) #define BBISHOP_MASK (0x00300000) #define BKBISHOP_MASK (0x00100000) #define BQBISHOP_MASK (0x00200000) #define BISHOP_MASK (0x00300030) #define WKNIGHT_MASK (0x000000C0) #define BKNIGHT_MASK (0x00C00000) #define BROOK_MASK (0x000C0000) #define BKROOK_MASK (0x00040000) #define BQROOK_MASK (0x00080000) #define WPAWN_MASK (0x0000FF00) #define BPAWN_MASK (0xFF000000) #define WPIECE_MASK (0x000000FF) #define BPIECE_MASK (0x00FF0000) #define WMINOR_MASK (WKNIGHT_MASK | WBISHOP_MASK) #define BMINOR_MASK (BKNIGHT_MASK | BBISHOP_MASK) #define MINOR_MASK (WMINOR_MASK | BMINOR_MASK) #define WMAJOR_MASK (WPIECE_MASK & ~WMINOR_MASK) #define BMAJOR_MASK (BPIECE_MASK & ~BMINOR_MASK) #define MAJOR_MASK (WMAJOR_MASK | BMAJOR_MASK) #define INFINITY (40.50*STATIC_PAWN_VALUE) #define ILLEGAL (-40*STATIC_PAWN_VALUE) #define WIN (-(ILLEGAL+1)) #define FORCED_WIN (WIN-127) #define MAX_EVAL (FORCED_WIN-20) #define MAX_MATERIAL (30.00*STATIC_PAWN_VALUE) #define STALEMATE 2 #define TIME_FORFEIT 3 #define UNKNOWN 4 #define DEFAULT_MOVE_TIME 10 #define POSN(x,y) ((y) + (x)*8) #define XPOS(p) ((p)>>3) #define YPOS(p) ((p)&7) #undef NORTH #undef SOUTH #undef EAST #undef WEST #define NORTH (1) #define SOUTH (-1) #define EAST (8) #define WEST (-8) #define NORTH_EAST (NORTH+EAST) #define NORTH_WEST (NORTH+WEST) #define SOUTH_EAST (SOUTH+EAST) #define SOUTH_WEST (SOUTH+WEST) #define WHITE_CASTLE_SHORT (1<<0) #define WHITE_CASTLE_LONG (1<<1) #define BLACK_CASTLE_SHORT (1<<2) #define BLACK_CASTLE_LONG (1<<3) #define WHITE_CASTLED (1<<4) #define BLACK_CASTLED (1<<5) #define FLAG_CHECK (1<<7) #define FLAG_PREV_CHECK (1<<8) #define FLAG_WHITE_PROMOTE (1<<11) #define FLAG_BLACK_PROMOTE (1<<12) #define FLAG_PROMOTE (FLAG_WHITE_PROMOTE | FLAG_BLACK_PROMOTE) #define FLAG_ACCEPT_DRAW (1<<13) #define FLAG_EVAL_DONE (1<<14) #define FLAG_WHITE_KINGSIDE (1<<15) #define FLAG_WHITE_QUEENSIDE (1<<16) #define FLAG_BLACK_KINGSIDE (1<<17) #define FLAG_BLACK_QUEENSIDE (1<<18) #define FLAG_NEED_PART2 (1<<20) #define FLAG_FORCED_DRAW (1<<21) #define FLAG_BAD_EVAL (1<<22) #define FLAG_EGTB_EVAL (1<<23) #define FLAG_GAME_OVER (1<<24) #define FLAG_LOST (1<<25) #define FLAG_EXTENDED (1<<26) #define FLAG_COMPUTER_WHITE (1<<27) #define FLAG_DONE_TACTICS (1<<28) #define FLAG_FUTILE (1<<29) #define FLAG_BLUNDER (1<<30) #define FLAG_KQ_SIDE (FLAG_BLACK_QUEENSIDE | FLAG_BLACK_KINGSIDE | FLAG_WHITE_QUEENSIDE | FLAG_WHITE_KINGSIDE) #define FLAG_WHITE_CAN_CASTLE (WHITE_CASTLE_SHORT | WHITE_CASTLE_LONG) #define FLAG_BLACK_CAN_CASTLE (BLACK_CASTLE_SHORT | BLACK_CASTLE_LONG) #define FLAG_CAN_CASTLE (FLAG_WHITE_CAN_CASTLE | FLAG_BLACK_CAN_CASTLE) #define REPITITION_LENGTH 101 #define mat_value(x) new_coefficients[IPIECE_VALUES + (x)] #if USE_STATIC_PAWN_VALUE #define PAWN_VALUE mat_value(PAWN) #endif #define KNIGHT_VALUE mat_value(KNIGHT) #define BISHOP_VALUE mat_value(BISHOP) #define ROOK_VALUE mat_value(ROOK) #define QUEEN_VALUE mat_value(QUEEN) #define KING_VALUE mat_value(KING) #define INITIAL_MATERIAL (KING_VALUE + QUEEN_VALUE + 2*ROOK_VALUE + 2*BISHOP_VALUE + 2*KNIGHT_VALUE + 8*PAWN_VALUE) typedef short int16; typedef unsigned short uint16; typedef unsigned uint32; typedef unsigned long long uint64; typedef enum {B_KING = -6,B_QUEEN = -5,B_ROOK = -4,B_BISHOP = -3, B_KNIGHT = -2,B_PAWN = -1, NONE=0, PAWN=1, KNIGHT=2, BISHOP=3, ROOK=4, QUEEN=5, KING=6} PieceT; typedef enum {A1=0, A2, A3, A4, A5, A6, A7, A8, B1, B2, B3, B4, B5, B6, B7, B8, C1, C2, C3, C4, C5, C6, C7, C8, D1, D2, D3, D4, D5, D6, D7, D8, E1, E2, E3, E4, E5, E6, E7, E8, F1, F2, F3, F4, F5, F6, F7, F8, G1, G2, G3, G4, G5, G6, G7, G8, H1, H2, H3, H4, H5, H6, H7, H8} SquareT; #ifndef DEBUG_FRIENDLY #define DEBUG_FRIENDLY 1 #endif #if DEBUG_FRIENDLY typedef SquareT Square; typedef PieceT Piece; #else typedef char Square; typedef char Piece; #endif typedef enum {OPENING=0, MIDDLE, ENDING, MATING} GameStage; typedef struct { Square from, to; int v; } Move; typedef struct { Piece board[NUM_SQUARES]; uint32 flags; int stage; short move_num; Square enpassent; unsigned char fifty_count; } SmallPos; typedef struct { /* use a short to hold evaluations */ #if LARGE_ETYPE etype v; #else int16 v; #endif #if STORE_LEAF_POS SmallPos pos; #endif } Eval; #if LEARN_EVAL typedef struct { etype v; uint32 flags; } LeafEval; #endif typedef struct { Piece p; Square pos; } PieceStruct; struct hash_entry { uint32 hash1; uint32 hash2; Eval low; Eval high; unsigned char depth_low; unsigned char depth_high; unsigned from:6; unsigned to:6; unsigned tag:4; unsigned char move_num; }; typedef struct Position { /* this section needs to be copied in do_move */ uint32 hash1, hash2; uint32 sliding_mask; /* mask of pieces that can "slide" (bishops, rooks, queens) */ uint32 pawns7th; /* mask of pawns on the 7th rank */ uint32 piece_mask; /* mask of which pieces are not pawns */ uint32 material_mask; /* mask of all pieces on the board */ Piece board[NUM_SQUARES]; /* the board itself */ char pboard[NUM_SQUARES]; /* pointers into the piece list */ PieceStruct pieces[32]; /* the piece list - this is never reordered as otherwise the masks would become invalid */ etype control[NUM_SQUARES]; /* the board control value for each square */ int cont[NUM_SQUARES]; /* who controls each square */ char safe_mobility[32]; /* mobility value for each piece */ char mobility[32]; /* mobility value for each piece */ int white_moves; /* whites total mobility */ int black_moves; /* blacks total mobility */ etype piece_values[32]; /* the value of each piece at the last eval call */ int stage; /* stage of the game */ uint32 piece_change; /* a bitmap of which pieces need to be recalculated */ uint32 hung_mask; /* a bitmap of pieces which are hung. This means they are on a square that the opponent controls */ uint32 pinned_mask; /* a bitmap of pieces which are pinned. */ uint32 attacking_mask; /* a bitmap of pieces which are attacking some enemy piece, and are thus being useful */ etype w_material; /* whites material value */ etype b_material; /* blacks material value */ etype board_control; /* the previous board control value */ etype expensive; /* the expensive eval components from the last eval */ etype evaluation; /* evaluation after a search */ uint32 flight[NUM_SQUARES]; /* a bitmap for each square which says what pieces can use this square as a safe retreat */ uint32 wpassed_pawn_mask; /* a mask of all the white passed pawns */ uint32 bpassed_pawn_mask; /* a mask of all the black passed pawns */ uint32 null_stoppable_pawn; /* a mask of the currently unstoppable pawns that would become stoppable if we null move */ uint32 null_unstoppable_pawn; /* a mask of the currently stoppable pawns that would become unstoppable if we null move */ uint64 white_holes; /* holes for white and black on ranks 2-5 */ uint64 black_holes; /* and this section doesn't get copied by do_move */ unsigned dont_copy; /* dummy variable */ uint32 topieces[NUM_SQUARES]; /* a bitmap for each square which says what pieces are supporting/attacking the square. This is the core of the move generator and the board control function */ #if USE_SLIDING_CONTROL uint32 xray_topieces[NUM_SQUARES]; /* a bitmap for each square which says what pieces are xray-supporting/attacking the square. */ #endif Move *moves; int num_moves; Move last_move; Move best_capture; etype tactics; /* the tactical eval component */ uint32 flags; uint32 flags2; int enpassent; int promotion; int fifty_count; int move_num; unsigned winner; struct hash_entry h_entry; struct Position *oldb; etype eval_result; } Position; struct state { Position position; int computer; int moved; float curquat[4]; float scale; int quit; int stop_search; float move_time; float time_limit; int always_think; int use_mulling; int use_pbrain; int flip_view; int ics_robot; int autoplay; int hash_table_size; int need_reset; Move game_record[MAX_GAME_MOVES]; Move converged_record[MAX_GAME_MOVES]; uint32 hash_list[MAX_GAME_MOVES]; /* for repitition */ int won; int colour; int rating_change; int demo_mode; int open; int display_position; int auto_exit; int brain_inserting; char white_player[100]; char black_player[100]; int moves_mulled; int analysed; int krating; int orating; int wtime; int btime; int game_time; int increment; int mulling; int current_depth; int last_book_move; int notified; int td_comp; int converged; int first_book_move; int first_book_move_index; int total_rounds; char notifyee[256]; char game_type[20]; #if STORE_LEAF_POS LeafEval leaf_eval[MAX_GAME_MOVES]; Position leaf_pos[MAX_GAME_MOVES]; short predicted_move[MAX_GAME_MOVES]; int stored_move_num; #endif }; #define WHITEPIECES(b) ((b)->pieces) #define BLACKPIECES(b) ((b)->pieces + 16) #define PIECES(b,player) ((player)>0?WHITEPIECES(b):BLACKPIECES(b)) #include "proto.h" #include "epdglue.h" #ifdef i386 static inline int ff_one(uint32 word) { __asm__("bsfl %1,%0" :"=r" (word) :"r" (word)); return word; } static inline int fl_one(uint32 word) { __asm__("bsrl %1,%0" :"=r" (word) :"r" (word)); return word; } #else static inline int ff_one(uint32 mask) { static const int first[16] = {-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; int ret=0; if (!(mask & 0xFFFF)) { mask >>= 16; ret += 16; } if (!(mask & 0xFF)) { mask >>= 8; ret += 8; } if (!(mask & 0xF)) { mask >>= 4; ret += 4; } return ret + first[mask & 0xF]; } static inline int fl_one(uint32 mask) { static const int last[16] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}; int ret=0; if (mask & 0xFFFF0000) { mask >>= 16; ret += 16; } if (mask & 0xFF00) { mask >>= 8; ret += 8; } if (mask & 0xF0) { mask >>= 4; ret += 4; } return ret + last[mask & 0xF]; } #endif /* determine if two pieces or players are the same color */ static inline int same_color(Piece p1, Piece p2) { return ((p1 ^ p2) >= 0); } static inline int is_white(Piece p1) { return p1 > 0; } static inline int is_black(Piece p1) { return p1 < 0; } static inline Square mirror_square(Square sq) { return sq ^ 7; } #define ABS(x) ((x)<0?-(x):(x)) #define SIGN(x) ((x)<0?-1:1) #define RAMP(x) ((x)<0?(x):RAMP_FACTOR*(x)) static inline int imin(int i1, int i2) { return i1 > i2? i2 : i1; } static inline int imax(int i1, int i2) { return i1 > i2? i1 : i2; } static inline etype emin(etype i1, etype i2) { return i1 > i2? i2 : i1; } static inline etype emax(etype i1, etype i2) { return i1 > i2? i1 : i2; } static inline etype shiftr1(etype x) { #if FLOAT_ETYPE return x*0.5; #else return x >> 1; #endif } static inline etype shiftr2(etype x) { #if FLOAT_ETYPE return x*0.25; #else return x >> 2; #endif } static inline PieceStruct *get_pboard(Position *b, Square pos) { if (b->pboard[pos] == -1) return NULL; return b->pieces + b->pboard[pos]; } static inline void set_pboard(Position *b, Square pos, PieceStruct *piece) { if (piece == NULL) b->pboard[pos] = -1; else b->pboard[pos] = piece - b->pieces; } static inline int is_zero_move(Move *move) { return (move->from == A1 && move->to == A1); } static inline int same_move(Move *m1, Move *m2) { return (m1->from == m2->from && m1->to == m2->to); } static inline void zero_move(Move *move) { move->from = move->to = A1; } static inline int bad_square(Square sq) { return ((sq & ~63) != 0); } static inline int white_square(Square sq) { return ((sq ^ (sq>>3)) & 1); } static inline int black_square(Square sq) { return !white_square(sq); } static inline int blacks_move(Position *b) { return (b->move_num & 1); } static inline int whites_move(Position *b) { return (!blacks_move(b)); } static inline int next_to_play(Position *b) { if (whites_move(b)) return 1; return -1; } static inline uint32 player_mask(Position *b) { if (whites_move(b)) return WHITE_MASK; return BLACK_MASK; } static inline Eval flip(Eval v) { v.v = -(v.v - 1); return v; } static inline Eval seteval(Eval v, etype value) { v.v = value; return v; } static inline Eval makeeval(Position *b, etype value) { Eval v; v.v = value; #if STORE_LEAF_POS memcpy(v.pos.board, b->board, sizeof(v.pos.board)); v.pos.flags = b->flags; v.pos.move_num = b->move_num; v.pos.enpassent = b->enpassent; v.pos.fifty_count = b->fifty_count; v.pos.stage = b->stage; #endif return v; } static inline int bit_count(uint32 x) { int count; for (count=0; x; count++) x &= (x-1); return count; } static inline struct hash_entry *hash_ptr(uint32 hash1) { extern struct hash_entry *hash_table; extern unsigned hash_table_size; uint32 hashindex = hash1 % hash_table_size; #if HASH_LEVELS hashindex &= ~(HASH_LEVELS - 1); #endif return &hash_table[hashindex]; } static inline void invert(etype *p1, etype *p2) { Square i; for (i=A1; i<=H8; i++) p1[i] = p2[mirror_square(i)]; } /* this determines if it is the computers move. This function is only valid during a search as the flag is setup at the start of the search code. This function is used to implement asymmetric search and eval factors */ static inline int computers_move(Position *b) { if (next_to_play(b) == 1) return ((b->flags & FLAG_COMPUTER_WHITE) != 0); return ((b->flags & FLAG_COMPUTER_WHITE) == 0); } extern char capture_map[2*KING+1][NUM_SQUARES][NUM_SQUARES]; extern char sliding_map[NUM_SQUARES][NUM_SQUARES]; extern char edge_square[NUM_SQUARES]; extern uint64 same_line_mask[NUM_SQUARES][NUM_SQUARES]; /* this checks whether 3 squares are in a line. Note that the order is important. same_line(A1, B2, C3) is true whereas same_line(B2, C3, A1) isn't. The answer is also always false if two of the squares are the same */ static inline int same_line(Square p1, Square p2, Square p3) { return sliding_map[p1][p2] && sliding_map[p1][p2] == sliding_map[p2][p3]; } /* given a direction of travel, will we move off the board by going one square in that direction. This relies on the legal values that a direction can take. */ static inline int off_board(Square sq, int dir) { dir = abs(edge_square[sq] + dir); return dir != 7 && dir & ~9; } /* this gives the distance from A1 or H8, whichever is closer */ static inline int corner_distance(Square sq) { static const char dist[64] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 2, 3, 4, 5, 6, 6, 2, 2, 2, 3, 4, 5, 5, 5, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 5, 5, 5, 4, 3, 2, 2, 2, 6, 6, 5, 4, 3, 2, 1, 1, 7, 6, 5, 4, 3, 2, 1, 0}; return dist[sq]; } struct hashvalue_entry { uint32 v1[2*KING+1][NUM_SQUARES]; uint32 v2[2*KING+1][NUM_SQUARES]; }; extern struct hashvalue_entry hash_values; static inline void add_hash(Position *b, Square pos, Piece p) { b->hash1 ^= hash_values.v1[p+KING][pos]; b->hash2 ^= hash_values.v2[p+KING][pos]; } static inline void remove_hash(Position *b, Square pos, Piece p) { b->hash1 ^= hash_values.v1[p+KING][pos]; b->hash2 ^= hash_values.v2[p+KING][pos]; } static inline int distance(Square sq1, Square sq2) { int xdist = abs(XPOS(sq1) - XPOS(sq2)); int ydist = abs(YPOS(sq1) - YPOS(sq2)); return imax(xdist, ydist); } extern int pop_count[256]; static inline int pop_count16(uint32 x) { return pop_count[(x)&0xFF] + pop_count[((x)>>8)&0xFF]; } static inline int pop_count32(uint32 x) { return pop_count16((x) & 0xFFFF) + pop_count16((x) >> 16); }