toga2-3.0.0.1SE1/0000755000175000017500000000000012155416555012571 5ustar oliverolivertoga2-3.0.0.1SE1/src/0000755000175000017500000000000012155416531013352 5ustar oliverolivertoga2-3.0.0.1SE1/src/vector.h0000644000175000017500000000114211125217316015017 0ustar oliveroliver // vector.h #ifndef VECTOR_H #define VECTOR_H // includes #include "util.h" // "constants" const int IncNone = 0; const int IncNb = 2 * 17 + 1; const int IncOffset = 17; const int DeltaNone = 0; const int DeltaNb = 2 * 119 + 1; const int DeltaOffset = 119; // macros #define DISTANCE(square_1,square_2) (Distance[DeltaOffset+((square_2)-(square_1))]) // variables extern int Distance[DeltaNb]; // functions extern void vector_init (); extern bool delta_is_ok (int delta); extern bool inc_is_ok (int inc); #endif // !defined VECTOR_H // end of vector.h toga2-3.0.0.1SE1/src/option.h0000644000175000017500000000106511125217320015024 0ustar oliveroliver // option.h #ifndef OPTION_H #define OPTION_H // includes #include "util.h" // functions extern void option_init (); extern void option_list (); extern bool option_set (const char var[], const char val[]); extern const char * option_get (const char var[]); extern bool option_get_bool (const char var[]); extern int option_get_int (const char var[]); extern const char * option_get_string (const char var[]); #endif // !defined OPTION_H // end of option.h toga2-3.0.0.1SE1/src/move_legal.h0000644000175000017500000000061511125217320015626 0ustar oliveroliver // move_legal.h #ifndef MOVE_LEGAL_H #define MOVE_LEGAL_H // includes #include "board.h" #include "list.h" #include "util.h" // functions extern bool move_is_pseudo (int move, board_t * board); extern bool quiet_is_pseudo (int move, board_t * board); extern bool pseudo_is_legal (int move, board_t * board); #endif // !defined MOVE_LEGAL_H // end of move_legal.h toga2-3.0.0.1SE1/src/square.h0000644000175000017500000000573411125217314015026 0ustar oliveroliver // square.h #ifndef SQUARE_H #define SQUARE_H // includes #include "colour.h" #include "util.h" // constants const int FileNb = 16; const int RankNb = 16; const int SquareNb = FileNb * RankNb; const int FileInc = +1; const int RankInc = +16; const int FileNone = 0; const int FileA = 0x4; const int FileB = 0x5; const int FileC = 0x6; const int FileD = 0x7; const int FileE = 0x8; const int FileF = 0x9; const int FileG = 0xA; const int FileH = 0xB; const int RankNone = 0; const int Rank1 = 0x4; const int Rank2 = 0x5; const int Rank3 = 0x6; const int Rank4 = 0x7; const int Rank5 = 0x8; const int Rank6 = 0x9; const int Rank7 = 0xA; const int Rank8 = 0xB; const int SquareNone = 0; const int A1=0x44, B1=0x45, C1=0x46, D1=0x47, E1=0x48, F1=0x49, G1=0x4A, H1=0x4B; const int A2=0x54, B2=0x55, C2=0x56, D2=0x57, E2=0x58, F2=0x59, G2=0x5A, H2=0x5B; const int A3=0x64, B3=0x65, C3=0x66, D3=0x67, E3=0x68, F3=0x69, G3=0x6A, H3=0x6B; const int A4=0x74, B4=0x75, C4=0x76, D4=0x77, E4=0x78, F4=0x79, G4=0x7A, H4=0x7B; const int A5=0x84, B5=0x85, C5=0x86, D5=0x87, E5=0x88, F5=0x89, G5=0x8A, H5=0x8B; const int A6=0x94, B6=0x95, C6=0x96, D6=0x97, E6=0x98, F6=0x99, G6=0x9A, H6=0x9B; const int A7=0xA4, B7=0xA5, C7=0xA6, D7=0xA7, E7=0xA8, F7=0xA9, G7=0xAA, H7=0xAB; const int A8=0xB4, B8=0xB5, C8=0xB6, D8=0xB7, E8=0xB8, F8=0xB9, G8=0xBA, H8=0xBB; const int Dark = 0; const int Light = 1; // macros #define SQUARE_IS_OK(square) ((((square)-0x44)&~0x77)==0) #define SQUARE_MAKE(file,rank) (((rank)<<4)|(file)) #define SQUARE_FILE(square) ((square)&0xF) #define SQUARE_RANK(square) ((square)>>4) #define SQUARE_FROM_64(square) (SquareFrom64[square]) #define SQUARE_TO_64(square) (SquareTo64[square]) #define SQUARE_IS_PROMOTE(square) (SquareIsPromote[square]) #define SQUARE_EP_DUAL(square) ((square)^16) #define SQUARE_COLOUR(square) (((square)^((square)>>4))&1) #define SQUARE_FILE_MIRROR(square) ((square)^0x0F) #define SQUARE_RANK_MIRROR(square) ((square)^0xF0) #define FILE_OPP(file) ((file)^0xF) #define RANK_OPP(rank) ((rank)^0xF) #define PAWN_RANK(square,colour) (SQUARE_RANK(square)^RankMask[colour]) #define PAWN_PROMOTE(square,colour) (PromoteRank[colour]|((square)&0xF)) // types typedef int sq_t; // "constants" extern const int SquareFrom64[64]; extern const int RankMask[ColourNb]; extern const int PromoteRank[ColourNb]; // variables extern int SquareTo64[SquareNb]; extern bool SquareIsPromote[SquareNb]; // functions extern void square_init (); extern int file_from_char (int c); extern int rank_from_char (int c); extern int file_to_char (int file); extern int rank_to_char (int rank); extern bool square_to_string (int square, char string[], int size); extern int square_from_string (const char string[]); #endif // !defined SQUARE_H // end of square.h toga2-3.0.0.1SE1/src/board.h0000644000175000017500000000447511125217322014615 0ustar oliveroliver // board.h #ifndef BOARD_H #define BOARD_H // includes #include "colour.h" #include "piece.h" #include "square.h" #include "util.h" // constants const int Empty = 0; const int Edge = Knight64; // HACK: uncoloured knight const int WP = WhitePawn256; const int WN = WhiteKnight256; const int WB = WhiteBishop256; const int WR = WhiteRook256; const int WQ = WhiteQueen256; const int WK = WhiteKing256; const int BP = BlackPawn256; const int BN = BlackKnight256; const int BB = BlackBishop256; const int BR = BlackRook256; const int BQ = BlackQueen256; const int BK = BlackKing256; const int FlagsNone = 0; const int FlagsWhiteKingCastle = 1 << 0; const int FlagsWhiteQueenCastle = 1 << 1; const int FlagsBlackKingCastle = 1 << 2; const int FlagsBlackQueenCastle = 1 << 3; const int StackSize = 4096; // macros #define KING_POS(board,colour) ((board)->piece[colour][0]) // types struct board_t { int piece_material[ColourNb]; // Thomas int square[SquareNb]; int pos[SquareNb]; sq_t piece[ColourNb][32]; // only 17 are needed int piece_size[ColourNb]; sq_t pawn[ColourNb][16]; // only 9 are needed int pawn_size[ColourNb]; int piece_nb; int number[16]; // only 12 are needed int pawn_file[ColourNb][FileNb]; int turn; int flags; int ep_square; int ply_nb; int sp; // TODO: MOVE ME? int cap_sq; int moving_piece; int opening; int endgame; uint64 key; uint64 pawn_key; uint64 material_key; uint64 stack[StackSize]; }; // functions extern bool board_is_ok (const board_t * board); extern void board_clear (board_t * board); extern void board_copy (board_t * dst, const board_t * src); extern void board_init_list (board_t * board); extern bool board_is_legal (const board_t * board); extern bool board_is_check (const board_t * board); extern bool board_is_mate (const board_t * board); extern bool board_is_stalemate (board_t * board); extern bool board_is_repetition (const board_t * board); extern int board_material (const board_t * board); extern int board_opening (const board_t * board); extern int board_endgame (const board_t * board); #endif // !defined BOARD_H // end of board.h toga2-3.0.0.1SE1/src/pst.cpp0000644000175000017500000002114611125217324014663 0ustar oliveroliver // pst.cpp // includes #include "option.h" #include "piece.h" #include "pst.h" #include "util.h" // macros #define P(piece_12,square_64,stage) (Pst[(piece_12)][(square_64)][(stage)]) // constants static const int A1=000, B1=001, C1=002, D1=003, E1=004, F1=005, G1=006, H1=007; static const int A2=010, B2=011, C2=012, D2=013, E2=014, F2=015, G2=016, H2=017; static const int A3=020, B3=021, C3=022, D3=023, E3=024, F3=025, G3=026, H3=027; static const int A4=030, B4=031, C4=032, D4=033, E4=034, F4=035, G4=036, H4=037; static const int A5=040, B5=041, C5=042, D5=043, E5=044, F5=045, G5=046, H5=047; static const int A6=050, B6=051, C6=052, D6=053, E6=054, F6=055, G6=056, H6=057; static const int A7=060, B7=061, C7=062, D7=063, E7=064, F7=065, G7=066, H7=067; static const int A8=070, B8=071, C8=072, D8=073, E8=074, F8=075, G8=076, H8=077; // constants and variables static /* const */ int PieceSquareWeight = 256; // 100% static /* const */ int PieceActivityWeight = 256; // 100% static /* const */ int KingSafetyWeight = 256; // 100% static /* const */ int PawnStructureWeight = 256; // 100% static const int PawnFileOpening = 5; static const int KnightCentreOpening = 5; static const int KnightCentreEndgame = 5; static const int KnightRankOpening = 5; static const int KnightBackRankOpening = 0; static const int KnightTrapped = 100; static const int BishopCentreOpening = 2; static const int BishopCentreEndgame = 3; static const int BishopBackRankOpening = 10; static const int BishopDiagonalOpening = 4; static const int RookFileOpening = 3; static const int QueenCentreOpening = 0; // was 0 static const int QueenCentreEndgame = 4; static const int QueenBackRankOpening = 5; static const int KingCentreEndgame = 12; static const int KingFileOpening = 10; static const int KingRankOpening = 10; // "constants" static const int PawnFile[8] = { -3, -1, +0, +1, +1, +0, -1, -3, }; static const int KnightLine[8] = { -4, -2, +0, +1, +1, +0, -2, -4, }; static const int KnightRank[8] = { -2, -1, +0, +1, +2, +3, +2, +1, }; static const int BishopLine[8] = { -3, -1, +0, +1, +1, +0, -1, -3, }; static const int RookFile[8] = { -2, -1, +0, +1, +1, +0, -1, -2, }; static const int QueenLine[8] = { -3, -1, +0, +1, +1, +0, -1, -3, }; static const int KingLine[8] = { -3, -1, +0, +1, +1, +0, -1, -3, }; static const int KingFile[8] = { +3, +4, +2, +0, +0, +2, +4, +3, }; static const int KingRank[8] = { +1, +0, -2, -3, -4, -5, -6, -7, }; // variables sint16 Pst[12][64][StageNb]; // prototypes static int square_make (int file, int rank); static int square_file (int square); static int square_rank (int square); static int square_opp (int square); // functions // pst_init() void pst_parameter() { // UCI options PieceSquareWeight = (option_get_int("Piece Square Activity") * 256 + 50) / 100; KingSafetyWeight = (option_get_int("King Safety") * 256 + 50) / 100; PawnStructureWeight = (option_get_int("Pawn Structure") * 256 + 50) / 100; } void pst_init() { int i; int piece, sq, stage; // UCI options pst_parameter(); // init for (piece = 0; piece < 12; piece++) { for (sq = 0; sq < 64; sq++) { for (stage = 0; stage < StageNb; stage++) { P(piece,sq,stage) = 0; } } } // pawns piece = WhitePawn12; // file for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += PawnFile[square_file(sq)] * PawnFileOpening; } // centre control P(piece,D3,Opening) += 10; P(piece,E3,Opening) += 10; P(piece,D4,Opening) += 20; P(piece,E4,Opening) += 20; P(piece,D5,Opening) += 10; P(piece,E5,Opening) += 10; // weight for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) = (P(piece,sq,Opening) * PawnStructureWeight) / 256; P(piece,sq,Endgame) = (P(piece,sq,Endgame) * PawnStructureWeight) / 256; } // knights piece = WhiteKnight12; // centre for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += KnightLine[square_file(sq)] * KnightCentreOpening; P(piece,sq,Opening) += KnightLine[square_rank(sq)] * KnightCentreOpening; P(piece,sq,Endgame) += KnightLine[square_file(sq)] * KnightCentreEndgame; P(piece,sq,Endgame) += KnightLine[square_rank(sq)] * KnightCentreEndgame; } // rank for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += KnightRank[square_rank(sq)] * KnightRankOpening; } // back rank for (sq = A1; sq <= H1; sq++) { // HACK: only first rank P(piece,sq,Opening) -= KnightBackRankOpening; } // "trapped" P(piece,A8,Opening) -= KnightTrapped; P(piece,H8,Opening) -= KnightTrapped; // weight for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) = (P(piece,sq,Opening) * PieceSquareWeight) / 256; P(piece,sq,Endgame) = (P(piece,sq,Endgame) * PieceSquareWeight) / 256; } // bishops piece = WhiteBishop12; // centre for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += BishopLine[square_file(sq)] * BishopCentreOpening; P(piece,sq,Opening) += BishopLine[square_rank(sq)] * BishopCentreOpening; P(piece,sq,Endgame) += BishopLine[square_file(sq)] * BishopCentreEndgame; P(piece,sq,Endgame) += BishopLine[square_rank(sq)] * BishopCentreEndgame; } // back rank for (sq = A1; sq <= H1; sq++) { // HACK: only first rank P(piece,sq,Opening) -= BishopBackRankOpening; } // main diagonals for (i = 0; i < 8; i++) { sq = square_make(i,i); P(piece,sq,Opening) += BishopDiagonalOpening; P(piece,square_opp(sq),Opening) += BishopDiagonalOpening; } // weight for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) = (P(piece,sq,Opening) * PieceSquareWeight) / 256; P(piece,sq,Endgame) = (P(piece,sq,Endgame) * PieceSquareWeight) / 256; } // rooks piece = WhiteRook12; // file for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += RookFile[square_file(sq)] * RookFileOpening; } // weight for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) = (P(piece,sq,Opening) * PieceSquareWeight) / 256; P(piece,sq,Endgame) = (P(piece,sq,Endgame) * PieceSquareWeight) / 256; } // queens piece = WhiteQueen12; // centre for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += QueenLine[square_file(sq)] * QueenCentreOpening; P(piece,sq,Opening) += QueenLine[square_rank(sq)] * QueenCentreOpening; P(piece,sq,Endgame) += QueenLine[square_file(sq)] * QueenCentreEndgame; P(piece,sq,Endgame) += QueenLine[square_rank(sq)] * QueenCentreEndgame; } // back rank for (sq = A1; sq <= H1; sq++) { // HACK: only first rank P(piece,sq,Opening) -= QueenBackRankOpening; } // weight for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) = (P(piece,sq,Opening) * PieceSquareWeight) / 256; P(piece,sq,Endgame) = (P(piece,sq,Endgame) * PieceSquareWeight) / 256; } // kings piece = WhiteKing12; // centre for (sq = 0; sq < 64; sq++) { P(piece,sq,Endgame) += KingLine[square_file(sq)] * KingCentreEndgame; P(piece,sq,Endgame) += KingLine[square_rank(sq)] * KingCentreEndgame; } // file for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += KingFile[square_file(sq)] * KingFileOpening; } // rank for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) += KingRank[square_rank(sq)] * KingRankOpening; } // weight for (sq = 0; sq < 64; sq++) { P(piece,sq,Opening) = (P(piece,sq,Opening) * KingSafetyWeight) / 256; P(piece,sq,Endgame) = (P(piece,sq,Endgame) * PieceSquareWeight) / 256; } // symmetry copy for black for (piece = 0; piece < 12; piece += 2) { // HACK for (sq = 0; sq < 64; sq++) { for (stage = 0; stage < StageNb; stage++) { P(piece+1,sq,stage) = -P(piece,square_opp(sq),stage); // HACK } } } } // square_make() static int square_make(int file, int rank) { ASSERT(file>=0&&file<8); ASSERT(rank>=0&&rank<8); return (rank << 3) | file; } // square_file() static int square_file(int square) { ASSERT(square>=0&&square<64); return square & 7; } // square_rank() static int square_rank(int square) { ASSERT(square>=0&&square<64); return square >> 3; } // square_opp() static int square_opp(int square) { ASSERT(square>=0&&square<64); return square ^ 070; } // end of pst.cpp toga2-3.0.0.1SE1/src/fen.h0000644000175000017500000000055411125217316014273 0ustar oliveroliver // fen.h #ifndef FEN_H #define FEN_H // includes #include "board.h" #include "util.h" // "constants" extern const char * const StartFen; // functions extern void board_from_fen (board_t * board, const char fen[]); extern bool board_to_fen (const board_t * board, char fen[], int size); #endif // !defined FEN_H // end of fen.h toga2-3.0.0.1SE1/src/list.cpp0000644000175000017500000000561011125217312015023 0ustar oliveroliver // list.cpp // includes #include "board.h" #include "list.h" #include "move.h" #include "util.h" #include "value.h" // constants static const bool UseStrict = true; // functions // list_is_ok() bool list_is_ok(const list_t * list) { if (list == NULL) return false; if (list->size < 0 || list->size >= ListSize) return false; return true; } // list_remove() void list_remove(list_t * list, int pos) { int i; ASSERT(list_is_ok(list)); ASSERT(pos>=0&&possize); for (i = pos; i < list->size-1; i++) { list->move[i] = list->move[i+1]; list->value[i] = list->value[i+1]; } list->size--; } // list_copy() void list_copy(list_t * dst, const list_t * src) { int i; ASSERT(dst!=NULL); ASSERT(list_is_ok(src)); dst->size = src->size; for (i = 0; i < src->size; i++) { dst->move[i] = src->move[i]; dst->value[i] = src->value[i]; } } // list_sort() void list_sort(list_t * list) { int size; int i, j; int move, value; ASSERT(list_is_ok(list)); // init size = list->size; list->value[size] = -32768; // HACK: sentinel // insert sort (stable) for (i = size-2; i >= 0; i--) { move = list->move[i]; value = list->value[i]; for (j = i; value < list->value[j+1]; j++) { list->move[j] = list->move[j+1]; list->value[j] = list->value[j+1]; } ASSERT(jmove[j] = move; list->value[j] = value; } // debug if (DEBUG) { for (i = 0; i < size-1; i++) { ASSERT(list->value[i]>=list->value[i+1]); } } } // list_contain() bool list_contain(const list_t * list, int move) { int i; ASSERT(list_is_ok(list)); ASSERT(move_is_ok(move)); for (i = 0; i < list->size; i++) { if (list->move[i] == move) return true; } return false; } // list_note() void list_note(list_t * list) { int i, move; ASSERT(list_is_ok(list)); for (i = 0; i < list->size; i++) { move = list->move[i]; ASSERT(move_is_ok(move)); list->value[i] = -move_order(move); } } // list_filter() void list_filter(list_t * list, board_t * board, move_test_t test, bool keep) { int pos; int i, move, value; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(test!=NULL); ASSERT(keep==true||keep==false); pos = 0; for (i = 0; i < LIST_SIZE(list); i++) { ASSERT(pos>=0&&pos<=i); move = LIST_MOVE(list,i); value = LIST_VALUE(list,i); if ((*test)(move,board) == keep) { list->move[pos] = move; list->value[pos] = value; pos++; } } ASSERT(pos>=0&&pos<=LIST_SIZE(list)); list->size = pos; // debug ASSERT(list_is_ok(list)); } // end of list.cpp toga2-3.0.0.1SE1/src/value.cpp0000644000175000017500000000573711125217314015200 0ustar oliveroliver // value.cpp // includes #include "piece.h" #include "search.h" #include "util.h" #include "value.h" // variables int ValuePiece[PieceNb]; // functions // value_init() void value_init() { int piece; // ValuePiece[] for (piece = 0; piece < PieceNb; piece++) ValuePiece[piece] = -1; ValuePiece[Empty] = 0; // needed? ValuePiece[Edge] = 0; // needed? ValuePiece[WP] = ValuePawn; ValuePiece[WN] = ValueKnight; ValuePiece[WB] = ValueBishop; ValuePiece[WR] = ValueRook; ValuePiece[WQ] = ValueQueen; ValuePiece[WK] = ValueKing; ValuePiece[BP] = ValuePawn; ValuePiece[BN] = ValueKnight; ValuePiece[BB] = ValueBishop; ValuePiece[BR] = ValueRook; ValuePiece[BQ] = ValueQueen; ValuePiece[BK] = ValueKing; } // value_is_ok() bool value_is_ok(int value) { if (value < -ValueInf || value > +ValueInf) return false; return true; } // range_is_ok() bool range_is_ok(int min, int max) { if (!value_is_ok(min)) return false; if (!value_is_ok(max)) return false; if (min >= max) return false; // alpha-beta-like ranges cannot be null return true; } // value_is_mate() bool value_is_mate(int value) { ASSERT(value_is_ok(value)); if (value < -ValueEvalInf || value > +ValueEvalInf) return true; return false; } // value_to_trans() int value_to_trans(int value, int height) { ASSERT(value_is_ok(value)); ASSERT(height_is_ok(height)); /* if (value < -ValueEvalInf) { value -= height; } else if (value > +ValueEvalInf) { value += height; } */ if (value < -ValueWin) { if(value < -ValueEvalInf) value -= height; else if (value > -ValueEvalInf) value -= ValuePly * height; } else if (value > +ValueWin) { if(value > ValueEvalInf) value += height; else if (value < +ValueWin) value += ValuePly * height; } ASSERT(value_is_ok(value)); return value; } // value_from_trans() int value_from_trans(int value, int height) { ASSERT(value_is_ok(value)); ASSERT(height_is_ok(height)); /*if (value < -ValueEvalInf) { value += height; } else if (value > +ValueEvalInf) { value -= height; }*/ if (value < -ValueWin) { if(value < -ValueEvalInf) value += height; else if (value > -ValueEvalInf) value += ValuePly * height; } else if (value > +ValueWin) { if(value > ValueEvalInf) value -= height; else if (value < ValueEvalInf) value -= ValuePly * height; } ASSERT(value_is_ok(value)); return value; } // value_to_mate() int value_to_mate(int value) { int dist; ASSERT(value_is_ok(value)); if (value < -ValueEvalInf) { dist = (ValueMate + value) / 2; ASSERT(dist>0); return -dist; } else if (value > +ValueEvalInf) { dist = (ValueMate - value + 1) / 2; ASSERT(dist>0); return +dist; } return 0; } // end of value.cpp toga2-3.0.0.1SE1/src/move_do.cpp0000644000175000017500000003670111125217316015511 0ustar oliveroliver // move_do.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "hash.h" #include "move.h" #include "move_do.h" #include "pawn.h" // TODO: bit.h #include "piece.h" #include "pst.h" #include "random.h" #include "util.h" #include "value.h" // variables static int CastleMask[SquareNb]; // prototypes static void square_clear (board_t * board, int square, int piece, bool update); static void square_set (board_t * board, int square, int piece, int pos, bool update); static void square_move (board_t * board, int from, int to, int piece, bool update); // functions // move_do_init() void move_do_init() { int sq; for (sq = 0; sq < SquareNb; sq++) CastleMask[sq] = 0xF; CastleMask[E1] &= ~FlagsWhiteKingCastle; CastleMask[H1] &= ~FlagsWhiteKingCastle; CastleMask[E1] &= ~FlagsWhiteQueenCastle; CastleMask[A1] &= ~FlagsWhiteQueenCastle; CastleMask[E8] &= ~FlagsBlackKingCastle; CastleMask[H8] &= ~FlagsBlackKingCastle; CastleMask[E8] &= ~FlagsBlackQueenCastle; CastleMask[A8] &= ~FlagsBlackQueenCastle; } // move_do() void move_do(board_t * board, int move, undo_t * undo) { int me, opp; int from, to; int piece, pos, capture; int old_flags, new_flags; int delta; int sq; int pawn, rook; ASSERT(board!=NULL); ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); ASSERT(board_is_legal(board)); // initialise undo undo->capture = false; undo->turn = board->turn; undo->flags = board->flags; undo->ep_square = board->ep_square; undo->ply_nb = board->ply_nb; undo->cap_sq = board->cap_sq; undo->moving_piece = board->moving_piece; undo->opening = board->opening; undo->endgame = board->endgame; undo->key = board->key; undo->pawn_key = board->pawn_key; undo->material_key = board->material_key; // init me = board->turn; opp = COLOUR_OPP(me); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; board->moving_piece = piece; ASSERT(COLOUR_IS(piece,me)); // update key stack ASSERT(board->spstack[board->sp++] = board->key; // update turn board->turn = opp; board->key ^= RANDOM_64(RandomTurn); // update castling rights old_flags = board->flags; new_flags = old_flags & CastleMask[from] & CastleMask[to]; board->flags = new_flags; board->key ^= Castle64[new_flags^old_flags]; // HACK // update en-passant square if ((sq=board->ep_square) != SquareNone) { board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA); board->ep_square = SquareNone; } if (PIECE_IS_PAWN(piece)) { delta = to - from; if (delta == +32 || delta == -32) { pawn = PAWN_MAKE(opp); if (board->square[to-1] == pawn || board->square[to+1] == pawn) { board->ep_square = (from + to) / 2; board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(to)-FileA); } } } // update move number (captures are handled later) board->ply_nb++; if (PIECE_IS_PAWN(piece)) board->ply_nb = 0; // conversion // update last square board->cap_sq = SquareNone; // remove the captured piece sq = to; if (MOVE_IS_EN_PASSANT(move)) sq = SQUARE_EP_DUAL(sq); if ((capture=board->square[sq]) != Empty) { ASSERT(COLOUR_IS(capture,opp)); ASSERT(!PIECE_IS_KING(capture)); undo->capture = true; undo->capture_square = sq; undo->capture_piece = capture; undo->capture_pos = board->pos[sq]; square_clear(board,sq,capture,true); board->ply_nb = 0; // conversion board->cap_sq = to; } // move the piece if (MOVE_IS_PROMOTE(move)) { // promote undo->pawn_pos = board->pos[from]; square_clear(board,from,piece,true); piece = move_promote(move); // insert the promote piece in MV order for (pos = board->piece_size[me]; pos > 0 && piece > board->square[board->piece[me][pos-1]]; pos--) // HACK ; square_set(board,to,piece,pos,true); board->cap_sq = to; } else { // normal move square_move(board,from,to,piece,true); } // move the rook in case of castling if (MOVE_IS_CASTLE(move)) { rook = Rook64 | COLOUR_FLAG(me); // HACK if (to == G1) { square_move(board,H1,F1,rook,true); } else if (to == C1) { square_move(board,A1,D1,rook,true); } else if (to == G8) { square_move(board,H8,F8,rook,true); } else if (to == C8) { square_move(board,A8,D8,rook,true); } else { ASSERT(false); } } // debug ASSERT(board_is_ok(board)); } // move_undo() void move_undo(board_t * board, int move, const undo_t * undo) { int me; int from, to; int piece, pos; int rook; ASSERT(board!=NULL); ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); // init me = undo->turn; from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[to]; ASSERT(COLOUR_IS(piece,me)); // castle if (MOVE_IS_CASTLE(move)) { rook = Rook64 | COLOUR_FLAG(me); // HACK if (to == G1) { square_move(board,F1,H1,rook,false); } else if (to == C1) { square_move(board,D1,A1,rook,false); } else if (to == G8) { square_move(board,F8,H8,rook,false); } else if (to == C8) { square_move(board,D8,A8,rook,false); } else { ASSERT(false); } } // move the piece backward if (MOVE_IS_PROMOTE(move)) { // promote ASSERT(piece==move_promote(move)); square_clear(board,to,piece,false); piece = PAWN_MAKE(me); pos = undo->pawn_pos; square_set(board,from,piece,pos,false); } else { // normal move square_move(board,to,from,piece,false); } // put the captured piece back if (undo->capture) { square_set(board,undo->capture_square,undo->capture_piece,undo->capture_pos,false); } // update board info board->turn = undo->turn; board->flags = undo->flags; board->ep_square = undo->ep_square; board->ply_nb = undo->ply_nb; board->cap_sq = undo->cap_sq; board->moving_piece = undo->moving_piece; board->opening = undo->opening; board->endgame = undo->endgame; board->key = undo->key; board->pawn_key = undo->pawn_key; board->material_key = undo->material_key; // update key stack ASSERT(board->sp>0); board->sp--; // debug ASSERT(board_is_ok(board)); ASSERT(board_is_legal(board)); } // move_do_null() void move_do_null(board_t * board, undo_t * undo) { int sq; ASSERT(board!=NULL); ASSERT(undo!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); // initialise undo undo->turn = board->turn; undo->ep_square = board->ep_square; undo->ply_nb = board->ply_nb; undo->cap_sq = board->cap_sq; undo->moving_piece = board->moving_piece; undo->key = board->key; // update key stack ASSERT(board->spstack[board->sp++] = board->key; // update turn board->turn = COLOUR_OPP(board->turn); board->key ^= RANDOM_64(RandomTurn); // update en-passant square sq = board->ep_square; if (sq != SquareNone) { board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA); board->ep_square = SquareNone; } // update move number board->ply_nb = 0; // HACK: null move is considered as a conversion // update last square board->cap_sq = SquareNone; board->moving_piece = PieceNone256; // debug ASSERT(board_is_ok(board)); } // move_undo_null() void move_undo_null(board_t * board, const undo_t * undo) { ASSERT(board!=NULL); ASSERT(undo!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); // update board info board->turn = undo->turn; board->ep_square = undo->ep_square; board->ply_nb = undo->ply_nb; board->cap_sq = undo->cap_sq; board->moving_piece = undo->moving_piece; board->key = undo->key; // update key stack ASSERT(board->sp>0); board->sp--; // debug ASSERT(board_is_ok(board)); } // square_clear() static void square_clear(board_t * board, int square, int piece, bool update) { int pos, piece_12, colour; int sq; int i, size; int sq_64; uint64 hash_xor; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(piece_is_ok(piece)); ASSERT(update==true||update==false); // init pos = board->pos[square]; ASSERT(pos>=0); piece_12 = PIECE_TO_12(piece); colour = PIECE_COLOUR(piece); // square ASSERT(board->square[square]==piece); board->square[square] = Empty; // piece list if (!PIECE_IS_PAWN(piece)) { // init size = board->piece_size[colour]; ASSERT(size>=1); // stable swap ASSERT(pos>=0&&pospos[square]==pos); board->pos[square] = -1; for (i = pos; i < size-1; i++) { sq = board->piece[colour][i+1]; board->piece[colour][i] = sq; ASSERT(board->pos[sq]==i+1); board->pos[sq] = i; } // size size--; board->piece[colour][size] = SquareNone; board->piece_size[colour] = size; } else { // init size = board->pawn_size[colour]; ASSERT(size>=1); // stable swap ASSERT(pos>=0&&pospos[square]==pos); board->pos[square] = -1; for (i = pos; i < size-1; i++) { sq = board->pawn[colour][i+1]; board->pawn[colour][i] = sq; ASSERT(board->pos[sq]==i+1); board->pos[sq] = i; } // size size--; board->pawn[colour][size] = SquareNone; board->pawn_size[colour] = size; // pawn "bitboard" board->pawn_file[colour][SQUARE_FILE(square)] ^= BIT(PAWN_RANK(square,colour)); } // material ASSERT(board->piece_nb>0); board->piece_nb--; ASSERT(board->number[piece_12]>0); board->number[piece_12]--; board->piece_material[colour] -= VALUE_PIECE(piece); // Thomas // update if (update) { // init sq_64 = SQUARE_TO_64(square); // PST board->opening -= PST(piece_12,sq_64,Opening); board->endgame -= PST(piece_12,sq_64,Endgame); // hash key hash_xor = RANDOM_64(RandomPiece+(piece_12^1)*64+sq_64); // HACK: ^1 for PolyGlot book board->key ^= hash_xor; if (PIECE_IS_PAWN(piece)) board->pawn_key ^= hash_xor; // material key board->material_key ^= RANDOM_64(piece_12*16+board->number[piece_12]); } } // square_set() static void square_set(board_t * board, int square, int piece, int pos, bool update) { int piece_12, colour; int sq; int i, size; int sq_64; uint64 hash_xor; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(piece_is_ok(piece)); ASSERT(pos>=0); ASSERT(update==true||update==false); // init piece_12 = PIECE_TO_12(piece); colour = PIECE_COLOUR(piece); // square ASSERT(board->square[square]==Empty); board->square[square] = piece; // piece list if (!PIECE_IS_PAWN(piece)) { // init size = board->piece_size[colour]; ASSERT(size>=0); // size size++; board->piece[colour][size] = SquareNone; board->piece_size[colour] = size; // stable swap ASSERT(pos>=0&&pos pos; i--) { sq = board->piece[colour][i-1]; board->piece[colour][i] = sq; ASSERT(board->pos[sq]==i-1); board->pos[sq] = i; } board->piece[colour][pos] = square; ASSERT(board->pos[square]==-1); board->pos[square] = pos; } else { // init size = board->pawn_size[colour]; ASSERT(size>=0); // size size++; board->pawn[colour][size] = SquareNone; board->pawn_size[colour] = size; // stable swap ASSERT(pos>=0&&pos pos; i--) { sq = board->pawn[colour][i-1]; board->pawn[colour][i] = sq; ASSERT(board->pos[sq]==i-1); board->pos[sq] = i; } board->pawn[colour][pos] = square; ASSERT(board->pos[square]==-1); board->pos[square] = pos; // pawn "bitboard" board->pawn_file[colour][SQUARE_FILE(square)] ^= BIT(PAWN_RANK(square,colour)); } // material ASSERT(board->piece_nb<32); board->piece_nb++;; ASSERT(board->number[piece_12]<9); board->number[piece_12]++; board->piece_material[colour] += VALUE_PIECE(piece); // Thomas // update if (update) { // init sq_64 = SQUARE_TO_64(square); // PST board->opening += PST(piece_12,sq_64,Opening); board->endgame += PST(piece_12,sq_64,Endgame); // hash key hash_xor = RANDOM_64(RandomPiece+(piece_12^1)*64+sq_64); // HACK: ^1 for PolyGlot book board->key ^= hash_xor; if (PIECE_IS_PAWN(piece)) board->pawn_key ^= hash_xor; // material key board->material_key ^= RANDOM_64(piece_12*16+(board->number[piece_12]-1)); } } // square_move() static void square_move(board_t * board, int from, int to, int piece, bool update) { int colour; int pos; int from_64, to_64; int piece_12; int piece_index; uint64 hash_xor; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); ASSERT(piece_is_ok(piece)); ASSERT(update==true||update==false); // init colour = PIECE_COLOUR(piece); pos = board->pos[from]; ASSERT(pos>=0); // from ASSERT(board->square[from]==piece); board->square[from] = Empty; ASSERT(board->pos[from]==pos); board->pos[from] = -1; // not needed // to ASSERT(board->square[to]==Empty); board->square[to] = piece; ASSERT(board->pos[to]==-1); board->pos[to] = pos; // piece list if (!PIECE_IS_PAWN(piece)) { ASSERT(board->piece[colour][pos]==from); board->piece[colour][pos] = to; } else { ASSERT(board->pawn[colour][pos]==from); board->pawn[colour][pos] = to; // pawn "bitboard" board->pawn_file[colour][SQUARE_FILE(from)] ^= BIT(PAWN_RANK(from,colour)); board->pawn_file[colour][SQUARE_FILE(to)] ^= BIT(PAWN_RANK(to,colour)); } // update if (update) { // init from_64 = SQUARE_TO_64(from); to_64 = SQUARE_TO_64(to); piece_12 = PIECE_TO_12(piece); // PST board->opening += PST(piece_12,to_64,Opening) - PST(piece_12,from_64,Opening); board->endgame += PST(piece_12,to_64,Endgame) - PST(piece_12,from_64,Endgame); // hash key piece_index = RandomPiece + (piece_12^1) * 64; // HACK: ^1 for PolyGlot book hash_xor = RANDOM_64(piece_index+to_64) ^ RANDOM_64(piece_index+from_64); board->key ^= hash_xor; if (PIECE_IS_PAWN(piece)) board->pawn_key ^= hash_xor; } } // end of move_do.cpp toga2-3.0.0.1SE1/src/piece.h0000644000175000017500000000660511125217316014613 0ustar oliveroliver // piece.h #ifndef PIECE_H #define PIECE_H // includes #include "colour.h" #include "util.h" // constants const int WhitePawnFlag = 1 << 2; const int BlackPawnFlag = 1 << 3; const int KnightFlag = 1 << 4; const int BishopFlag = 1 << 5; const int RookFlag = 1 << 6; const int KingFlag = 1 << 7; const int PawnFlags = WhitePawnFlag | BlackPawnFlag; const int QueenFlags = BishopFlag | RookFlag; const int PieceNone64 = 0; const int WhitePawn64 = WhitePawnFlag; const int BlackPawn64 = BlackPawnFlag; const int Knight64 = KnightFlag; const int Bishop64 = BishopFlag; const int Rook64 = RookFlag; const int Queen64 = QueenFlags; const int King64 = KingFlag; const int PieceNone256 = 0; const int WhitePawn256 = WhitePawn64 | WhiteFlag; const int BlackPawn256 = BlackPawn64 | BlackFlag; const int WhiteKnight256 = Knight64 | WhiteFlag; const int BlackKnight256 = Knight64 | BlackFlag; const int WhiteBishop256 = Bishop64 | WhiteFlag; const int BlackBishop256 = Bishop64 | BlackFlag; const int WhiteRook256 = Rook64 | WhiteFlag; const int BlackRook256 = Rook64 | BlackFlag; const int WhiteQueen256 = Queen64 | WhiteFlag; const int BlackQueen256 = Queen64 | BlackFlag; const int WhiteKing256 = King64 | WhiteFlag; const int BlackKing256 = King64 | BlackFlag; const int PieceNb = 256; const int WhitePawn12 = 0; const int BlackPawn12 = 1; const int WhiteKnight12 = 2; const int BlackKnight12 = 3; const int WhiteBishop12 = 4; const int BlackBishop12 = 5; const int WhiteRook12 = 6; const int BlackRook12 = 7; const int WhiteQueen12 = 8; const int BlackQueen12 = 9; const int WhiteKing12 = 10; const int BlackKing12 = 11; // macros #define PAWN_MAKE(colour) (PawnMake[colour]) #define PAWN_OPP(pawn) ((pawn)^(WhitePawn256^BlackPawn256)) #define PIECE_COLOUR(piece) (((piece)&3)-1) #define PIECE_TYPE(piece) ((piece)&~3) #define PIECE_IS_PAWN(piece) (((piece)&PawnFlags)!=0) #define PIECE_IS_KNIGHT(piece) (((piece)&KnightFlag)!=0) #define PIECE_IS_BISHOP(piece) (((piece)&QueenFlags)==BishopFlag) #define PIECE_IS_ROOK(piece) (((piece)&QueenFlags)==RookFlag) #define PIECE_IS_QUEEN(piece) (((piece)&QueenFlags)==QueenFlags) #define PIECE_IS_KING(piece) (((piece)&KingFlag)!=0) #define PIECE_IS_SLIDER(piece) (((piece)&QueenFlags)!=0) #define PIECE_TO_12(piece) (PieceTo12[piece]) #define PIECE_ORDER(piece) (PieceOrder[piece]) #define PAWN_MOVE_INC(colour) (PawnMoveInc[colour]) #define PIECE_INC(piece) (PieceInc[piece]) // types typedef int inc_t; // "constants" extern const int PawnMake[ColourNb]; extern const int PieceFrom12[12]; extern const inc_t PawnMoveInc[ColourNb]; extern const inc_t KnightInc[8+1]; extern const inc_t BishopInc[4+1]; extern const inc_t RookInc[4+1]; extern const inc_t QueenInc[8+1]; extern const inc_t KingInc[8+1]; // variables extern int PieceTo12[PieceNb]; extern int PieceOrder[PieceNb]; extern const inc_t * PieceInc[PieceNb]; // functions extern void piece_init (); extern bool piece_is_ok (int piece); extern int piece_from_12 (int piece_12); extern int piece_to_char (int piece); extern int piece_from_char (int c); #endif // !defined PIECE_H // end of piece.h toga2-3.0.0.1SE1/src/color.h0000644000175000017500000000074211125213432014633 0ustar oliveroliver// color.h #ifndef COLOUR_H #define COLOUR_H // macros #define COLOUR_IS_OK(color) (((color)&~1)==0) #define COLOUR_IS_WHITE(color) ((color)==0) #define COLOUR_IS_BLACK(color) ((color)!=0) #define COLOUR_IS(piece,color) (FLAG_IS((piece),COLOUR_FLAG(color))) #define FLAG_IS(piece,flag) (((piece)&(flag))!=0) #define COLOUR_OPP(color) ((color)^(0^1)) #define COLOUR_FLAG(color) ((color)+1) #endif // !defined COLOUR_H // end of color.h toga2-3.0.0.1SE1/src/move_gen.h0000644000175000017500000000116211125217324015315 0ustar oliveroliver // move_gen.h #ifndef MOVE_GEN_H #define MOVE_GEN_H // includes #include "attack.h" #include "board.h" #include "list.h" #include "util.h" // functions extern void gen_legal_moves (list_t * list, board_t * board); extern void gen_moves (list_t * list, const board_t * board); extern void gen_captures (list_t * list, const board_t * board); extern void gen_quiet_moves (list_t * list, const board_t * board); extern void add_pawn_move (list_t * list, int from, int to); extern void add_promote (list_t * list, int move); #endif // !defined MOVE_GEN_H // end of move_gen.h toga2-3.0.0.1SE1/src/search.h0000644000175000017500000000526012102726702014767 0ustar oliveroliver // search.h #ifndef SEARCH_H #define SEARCH_H // includes #include #include "board.h" #include "list.h" #include "move.h" #include "util.h" // constants const int MultiPVMax = 10; const int MaxThreads = 16; const int DepthMax = 64; const int HeightMax = 256; const int HeightNone = -1; const int SearchNormal = 0; const int SearchShort = 1; const int SearchUnknown = 0; const int SearchUpper = 1; const int SearchLower = 2; const int SearchExact = 3; // types struct search_multipv_t { int mate; int depth; int max_depth; int value; double time; sint64 node_nb; char pv_string[512]; }; struct search_param_t { int move; int best_move; int threat_move; bool reduced; }; struct search_input_t { board_t board[1]; list_t list[1]; bool infinite; bool depth_is_limited; int depth_limit; int multipv; volatile bool exit_engine; bool time_is_limited; double time_limit_1; double time_limit_2; }; struct search_info_t { jmp_buf buf; bool can_stop; volatile bool stop; volatile bool stopped; volatile bool exited; int check_nb; int check_inc; double last_time; }; struct search_root_t { list_t list[1]; int depth; int move; int move_pos; int move_nb; int last_value; bool bad_1; bool bad_2; bool change; bool easy; bool flag; }; struct search_best_t { int move; int value; int flags; int depth; mv_t pv[HeightMax]; }; struct search_current_t { board_t board[1]; my_timer_t timer[1]; int max_depth; int act_iteration; // Thomas int multipv; int CheckNb; int CheckDepth; sint64 node_nb; double time; double speed; double cpu; }; // variables extern search_input_t SearchInput[1]; extern search_info_t SearchInfo[MaxThreads][1]; extern search_best_t SearchBest[MaxThreads][MultiPVMax]; extern search_root_t SearchRoot[MaxThreads][1]; extern search_current_t SearchCurrent[MaxThreads][1]; extern int NumberThreads; // functions extern bool depth_is_ok (int depth); extern bool height_is_ok (int height); extern void search_clear (); extern void search (); extern void search_smp (int ThreadId); extern void search_update_best (int ThreadId); extern void search_update_root (int ThreadId); extern void search_update_current (int ThreadId); extern void search_check (int ThreadId); extern void start_suspend_threads(); extern void resume_threads(); extern void exit_threads(); #endif // !defined SEARCH_H // end of search.h toga2-3.0.0.1SE1/src/main.h0000644000175000017500000000032311125213424014435 0ustar oliveroliver#ifndef MAIN_H_ #define MAIN_H_ //#define LOCK #pragma warning( disable : 4100 ) // Level 4 unreferenced formal parameter -> input.cpp/egtb.cpp/tbdecode.h char file_name[256]; #endif // MAIN_H_ toga2-3.0.0.1SE1/src/probe.cpp0000644000175000017500000000530211125217324015160 0ustar oliveroliver // probe.cpp // includes #ifdef _WIN32 #include #else #include #include #endif #include "util.h" #include "board.h" #include "probe.h" #include "protocol.h" #include "search.h" // "constants" enum {_EMPTY,_WKING,_WQUEEN,_WROOK,_WBISHOP,_WKNIGHT,_WPAWN, _BKING,_BQUEEN,_BROOK,_BBISHOP,_BKNIGHT,_BPAWN}; enum {LOAD_NONE,LOAD_4MEN,SMART_LOAD,LOAD_5MEN}; static int egbb_load_type = LOAD_4MEN; // macros /* Load the dll and get the address of the load and probe functions. */ #ifdef _MSC_VER #define EGBB_NAME "egbbdll.dll" #else #define EGBB_NAME "egbbso.so" #define HMODULE void* #define LoadLibrary(x) dlopen(x,RTLD_LAZY) #define FreeLibrary(x) dlclose(x) #define GetProcAddress dlsym #endif // variables bool egbb_is_loaded; // functions int LoadEgbbLibrary(char* main_path,uint32 egbb_cache_size) { static HMODULE hmod; PLOAD_EGBB load_egbb; char path[256]; strcpy(path,main_path); strcat(path,EGBB_NAME); if (hmod) FreeLibrary(hmod); if(hmod = LoadLibrary(path)) { load_egbb = (PLOAD_EGBB) GetProcAddress(hmod,"load_egbb_5men"); probe_egbb = (PPROBE_EGBB) GetProcAddress(hmod,"probe_egbb_5men"); load_egbb(main_path,egbb_cache_size,egbb_load_type); return true; } else { //printf("EgbbProbe not Loaded!\n"); return false; } } /* Probe: probe bitbase. */ int probe_bitbases(board_t * board, int& score) { int piece[5]; int square[5]; int from; int count; sq_t * ptr; count = 0; piece[0] = _EMPTY; piece[1] = _EMPTY; piece[2] = _EMPTY; square[0] = _EMPTY; square[1] = _EMPTY; square[2] = _EMPTY; for (ptr = &board->piece[White][1]; (from=*ptr) != SquareNone; ptr++) { square[count] = SquareTo64[from]; piece[count++] = -((PIECE_TO_12(board->square[from]) >> 1) - 6); } for (ptr = &board->pawn[White][0]; (from=*ptr) != SquareNone; ptr++) { square[count] = SquareTo64[from]; piece[count++] = _WPAWN; } for (ptr = &board->piece[Black][1]; (from=*ptr) != SquareNone; ptr++) { square[count] = SquareTo64[from]; piece[count++] = -((PIECE_TO_12(board->square[from]) >> 1) - 12); } for (ptr = &board->pawn[Black][0]; (from=*ptr) != SquareNone; ptr++) { square[count] = SquareTo64[from]; piece[count++] = _BPAWN; } //EnterCriticalSection(&CriticalSection); score = probe_egbb(board->turn,SquareTo64[board->piece[White][0]],SquareTo64[board->piece[Black][0]], piece[0],square[0],piece[1],square[1],piece[2],square[2]); //LeaveCriticalSection(&CriticalSection); if(score != _NOTFOUND) { return true; } return false; } // end of probe.cpp toga2-3.0.0.1SE1/src/util.h0000644000175000017500000000554611125221746014510 0ustar oliveroliver // util.h #ifndef UTIL_H #define UTIL_H // includes #include // constants #undef FALSE #define FALSE 0 #undef TRUE #define TRUE 1 #ifdef DEBUG # undef DEBUG # define DEBUG TRUE #else # define DEBUG FALSE #endif #ifdef _MSC_VER # define S64_FORMAT "%I64d" # define U64_FORMAT "%016I64X" #else # define S64_FORMAT "%lld" # define U64_FORMAT "%016llX" #endif // macros #if defined(_MSC_VER) && !defined(__MINGW32__) # define S64(u) (u##i64) # define U64(u) (u##ui64) #else # define S64(u) (u##LL) # define U64(u) (u##ULL) #endif #undef ASSERT #if DEBUG # define ASSERT(a) { if (!(a)) my_fatal("file \"%s\", line %d, assertion \"" #a "\" failed\n",__FILE__,__LINE__); } #else # define ASSERT(a) #endif // types typedef signed char sint8; typedef unsigned char uint8; typedef signed short sint16; typedef unsigned short uint16; typedef signed int sint32; typedef unsigned int uint32; #ifdef _MSC_VER typedef signed __int64 sint64; typedef unsigned __int64 uint64; #else typedef signed long long int sint64; typedef unsigned long long int uint64; #endif #ifndef _WIN32 #include typedef struct { int volatile value; pthread_mutex_t mutex; pthread_cond_t cond; } my_sem_t; #endif struct my_timer_t { double start_real; double start_cpu; double elapsed_real; double elapsed_cpu; bool running; }; // functions extern void util_init (); extern void my_random_init (); extern int my_random (int n); extern sint64 my_atoll (const char string[]); extern int my_round (double x); extern void * my_malloc (int size); extern void my_free (void * address); extern void my_fatal (const char format[], ...); extern bool my_file_read_line (FILE * file, char string[], int size); extern bool my_string_empty (const char string[]); extern bool my_string_equal (const char string_1[], const char string_2[]); extern char * my_strdup (const char string[]); extern void my_string_clear (const char * * variable); extern void my_string_set (const char * * variable, const char string[]); extern void my_timer_reset (my_timer_t * timer); extern void my_timer_start (my_timer_t * timer); extern void my_timer_stop (my_timer_t * timer); extern double my_timer_elapsed_real (const my_timer_t * timer); extern double my_timer_elapsed_cpu (const my_timer_t * timer); extern double my_timer_cpu_usage (const my_timer_t * timer); #ifndef _WIN32 extern void my_sem_init(my_sem_t *sem, int value); extern void my_sem_post(my_sem_t *sem); extern void my_sem_wait(my_sem_t *sem); #endif #endif // !defined UTIL_H // end of util.h toga2-3.0.0.1SE1/src/square.cpp0000644000175000017500000000444011125217322015351 0ustar oliveroliver // square.cpp // includes #include "colour.h" #include "square.h" #include "util.h" // "constants" const int SquareFrom64[64] = { 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, }; const int RankMask[ColourNb] = { 0, 0xF }; const int PromoteRank[ColourNb] = { 0xB0, 0x40 }; // variables int SquareTo64[SquareNb]; bool SquareIsPromote[SquareNb]; // functions // square_init() void square_init() { int sq; // SquareTo64[] for (sq = 0; sq < SquareNb; sq++) SquareTo64[sq] = -1; for (sq = 0; sq < 64; sq++) { SquareTo64[SquareFrom64[sq]] = sq; } // SquareIsPromote[] for (sq = 0; sq < SquareNb; sq++) { SquareIsPromote[sq] = SQUARE_IS_OK(sq) && (SQUARE_RANK(sq) == Rank1 || SQUARE_RANK(sq) == Rank8); } } // file_from_char() int file_from_char(int c) { ASSERT(c>='a'&&c<='h'); return FileA + (c - 'a'); } // rank_from_char() int rank_from_char(int c) { ASSERT(c>='1'&&c<='8'); return Rank1 + (c - '1'); } // file_to_char() int file_to_char(int file) { ASSERT(file>=FileA&&file<=FileH); return 'a' + (file - FileA); } // rank_to_char() int rank_to_char(int rank) { ASSERT(rank>=Rank1&&rank<=Rank8); return '1' + (rank - Rank1); } // square_to_string() bool square_to_string(int square, char string[], int size) { ASSERT(SQUARE_IS_OK(square)); ASSERT(string!=NULL); ASSERT(size>=3); if (size < 3) return false; string[0] = file_to_char(SQUARE_FILE(square)); string[1] = rank_to_char(SQUARE_RANK(square)); string[2] = '\0'; return true; } // square_from_string() int square_from_string(const char string[]) { int file, rank; ASSERT(string!=NULL); if (string[0] < 'a' || string[0] > 'h') return SquareNone; if (string[1] < '1' || string[1] > '8') return SquareNone; if (string[2] != '\0') return SquareNone; file = file_from_char(string[0]); rank = rank_from_char(string[1]); return SQUARE_MAKE(file,rank); } // end of square.cpp toga2-3.0.0.1SE1/src/util.cpp0000644000175000017500000001342211125217314015027 0ustar oliveroliver // util.cpp // includes #include #include #include #include #include #include #include #include #include "posix.h" #include "util.h" // functions // util_init() void util_init() { setvbuf(stdin,NULL,_IONBF,0); setvbuf(stdout,NULL,_IONBF,0); // _IOLBF breaks on Windows! } // my_random_init() void my_random_init() { srand(time(NULL)); } // my_random() int my_random(int n) { double r; ASSERT(n>0); r = double(rand()) / (double(RAND_MAX) + 1.0); return int(floor(r*double(n))); } // my_atoll() sint64 my_atoll(const char string[]) { sint64 n; sscanf(string,S64_FORMAT,&n); return n; } // my_round() int my_round(double x) { return int(floor(x+0.5)); } // my_malloc() void * my_malloc(int size) { void * address; ASSERT(size>0); address = malloc(size); if (address == NULL) my_fatal("my_malloc(): malloc(): %s\n",strerror(errno)); return address; } // my_free() void my_free(void * address) { ASSERT(address!=NULL); free(address); } // my_fatal() void my_fatal(const char format[], ...) { va_list ap; ASSERT(format!=NULL); va_start(ap,format); vfprintf(stderr,format,ap); va_end(ap); exit(EXIT_FAILURE); // abort(); } // my_file_read_line() bool my_file_read_line(FILE * file, char string[], int size) { char * ptr; ASSERT(file!=NULL); ASSERT(string!=NULL); ASSERT(size>0); if (fgets(string,size,file) == NULL) { if (feof(file)) { return false; } else { // error my_fatal("my_file_read_line(): fgets(): %s\n",strerror(errno)); } } // suppress '\n' ptr = strchr(string,'\n'); if (ptr != NULL) *ptr = '\0'; return true; } // my_string_empty() bool my_string_empty(const char string[]) { return string == NULL || string[0] == '\0'; } // my_string_equal() bool my_string_equal(const char string_1[], const char string_2[]) { int c1, c2; ASSERT(string_1!=NULL); ASSERT(string_2!=NULL); while (true) { c1 = *string_1++; c2 = *string_2++; if (tolower(c1) != tolower(c2)) return false; if (c1 == '\0') return true; } return false; } // my_strdup() char * my_strdup(const char string[]) { char * address; ASSERT(string!=NULL); // strdup() is not ANSI C address = (char *) my_malloc(strlen(string)+1); strcpy(address,string); return address; } // my_string_clear() void my_string_clear(const char * * variable) { ASSERT(variable!=NULL); if (*variable != NULL) { my_free((void*)(*variable)); *variable = NULL; } } // my_string_set() void my_string_set(const char * * variable, const char string[]) { ASSERT(variable!=NULL); ASSERT(string!=NULL); if (*variable != NULL) my_free((void*)(*variable)); *variable = my_strdup(string); } // my_timer_reset() void my_timer_reset(my_timer_t * timer) { ASSERT(timer!=NULL); timer->start_real = 0.0; timer->start_cpu = 0.0; timer->elapsed_real = 0.0; timer->elapsed_cpu = 0.0; timer->running = false; } // my_timer_start() void my_timer_start(my_timer_t * timer) { ASSERT(timer!=NULL); ASSERT(timer->start_real==0.0); ASSERT(timer->start_cpu==0.0); ASSERT(!timer->running); timer->running = true; timer->start_real = now_real(); timer->start_cpu = now_cpu(); } // my_timer_stop() void my_timer_stop(my_timer_t * timer) { ASSERT(timer!=NULL); ASSERT(timer->running); timer->elapsed_real += now_real() - timer->start_real; timer->elapsed_cpu += now_cpu() - timer->start_cpu; timer->start_real = 0.0; timer->start_cpu = 0.0; timer->running = false; } // my_timer_elapsed_real() double my_timer_elapsed_real(const my_timer_t * timer) { double elapsed; ASSERT(timer!=NULL); elapsed = timer->elapsed_real; if (timer->running) elapsed += now_real() - timer->start_real; if (elapsed < 0.0) elapsed = 0.0; return elapsed; } // my_timer_elapsed_cpu() double my_timer_elapsed_cpu(const my_timer_t * timer) { double elapsed; ASSERT(timer!=NULL); elapsed = timer->elapsed_cpu; if (timer->running) elapsed += now_cpu() - timer->start_cpu; if (elapsed < 0.0) elapsed = 0.0; return elapsed; } // my_timer_cpu_usage() double my_timer_cpu_usage(const my_timer_t * timer) { double real, cpu; double usage; ASSERT(timer!=NULL); real = my_timer_elapsed_real(timer); cpu = my_timer_elapsed_cpu(timer); if (real <= 0.0 || cpu <= 0.0) return 0.0; usage = cpu / real; if (usage >= 1.0) usage = 1.0; return usage; } #ifndef _WIN32 // The standard semaphore functions sem_init,sem_post,sem_wait, etc... // compile on MACOSX but do not work. // See // http://64.68.157.89/forum/viewtopic.php?t=24108&postdays=0&postorder=asc&topic_view=&start=30 // For portability we provide our own versions. // my_sem_init() void my_sem_init(my_sem_t *sem, int value){ sem->value=value; pthread_mutex_init(&(sem->mutex),NULL); pthread_cond_init(&(sem->cond),NULL); } // my_sem_post() void my_sem_post(my_sem_t *sem){ pthread_mutex_lock(&(sem->mutex)); sem->value++; pthread_cond_signal(&(sem->cond)); pthread_mutex_unlock(&(sem->mutex)); } // my_sem_wait() void my_sem_wait(my_sem_t *sem){ pthread_mutex_lock(&(sem->mutex)); while(sem->value==0){ pthread_cond_wait(&(sem->cond),&(sem->mutex)); } sem->value--; pthread_mutex_unlock(&(sem->mutex)); } #endif // end of util.cpp toga2-3.0.0.1SE1/src/move_evasion.h0000644000175000017500000000102511125217324016206 0ustar oliveroliver // move_evasion.h #ifndef MOVE_EVASION_H #define MOVE_EVASION_H // includes #include "attack.h" #include "board.h" #include "list.h" #include "util.h" // functions extern void gen_legal_evasions (list_t * list, const board_t * board, const attack_t * attack); extern void gen_pseudo_evasions (list_t * list, const board_t * board, const attack_t * attack); extern bool legal_evasion_exist (const board_t * board, const attack_t * attack); #endif // !defined MOVE_EVASION_H // end of move_evasion.h toga2-3.0.0.1SE1/src/move_check.h0000644000175000017500000000053211125217314015620 0ustar oliveroliver // move_check.h #ifndef MOVE_CHECK_H #define MOVE_CHECK_H // includes #include "board.h" #include "list.h" #include "util.h" // functions extern void gen_quiet_checks (list_t * list, board_t * board); extern bool move_is_check (int move, board_t * board); #endif // !defined MOVE_CHECK_H // end of move_check.h toga2-3.0.0.1SE1/src/attack.cpp0000644000175000017500000002635011125217322015324 0ustar oliveroliver // attack.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "move.h" #include "piece.h" #include "util.h" #include "vector.h" // variables int DeltaIncLine[DeltaNb]; int DeltaIncAll[DeltaNb]; int DeltaMask[DeltaNb]; int IncMask[IncNb]; static int PieceCode[PieceNb]; static int PieceDeltaSize[4][256]; // 4kB static int PieceDeltaDelta[4][256][4]; // 16 kB // prototypes static void add_attack (int piece, int king, int target); // functions // attack_init() void attack_init() { int delta, inc; int piece; int dir, dist; int size; int king; int from, to; int pos; // clear for (delta = 0; delta < DeltaNb; delta++) { DeltaIncLine[delta] = IncNone; DeltaIncAll[delta] = IncNone; DeltaMask[delta] = 0; } for (inc = 0; inc < IncNb; inc++) { IncMask[inc] = 0; } // pawn attacks DeltaMask[DeltaOffset-17] |= BlackPawnFlag; DeltaMask[DeltaOffset-15] |= BlackPawnFlag; DeltaMask[DeltaOffset+15] |= WhitePawnFlag; DeltaMask[DeltaOffset+17] |= WhitePawnFlag; // knight attacks for (dir = 0; dir < 8; dir++) { delta = KnightInc[dir]; ASSERT(delta_is_ok(delta)); ASSERT(DeltaIncAll[DeltaOffset+delta]==IncNone); DeltaIncAll[DeltaOffset+delta] = delta; DeltaMask[DeltaOffset+delta] |= KnightFlag; } // bishop/queen attacks for (dir = 0; dir < 4; dir++) { inc = BishopInc[dir]; ASSERT(inc!=IncNone); IncMask[IncOffset+inc] |= BishopFlag; for (dist = 1; dist < 8; dist++) { delta = inc*dist; ASSERT(delta_is_ok(delta)); ASSERT(DeltaIncLine[DeltaOffset+delta]==IncNone); DeltaIncLine[DeltaOffset+delta] = inc; ASSERT(DeltaIncAll[DeltaOffset+delta]==IncNone); DeltaIncAll[DeltaOffset+delta] = inc; DeltaMask[DeltaOffset+delta] |= BishopFlag; } } // rook/queen attacks for (dir = 0; dir < 4; dir++) { inc = RookInc[dir]; ASSERT(inc!=IncNone); IncMask[IncOffset+inc] |= RookFlag; for (dist = 1; dist < 8; dist++) { delta = inc*dist; ASSERT(delta_is_ok(delta)); ASSERT(DeltaIncLine[DeltaOffset+delta]==IncNone); DeltaIncLine[DeltaOffset+delta] = inc; ASSERT(DeltaIncAll[DeltaOffset+delta]==IncNone); DeltaIncAll[DeltaOffset+delta] = inc; DeltaMask[DeltaOffset+delta] |= RookFlag; } } // king attacks for (dir = 0; dir < 8; dir++) { delta = KingInc[dir]; ASSERT(delta_is_ok(delta)); DeltaMask[DeltaOffset+delta] |= KingFlag; } // PieceCode[] for (piece = 0; piece < PieceNb; piece++) { PieceCode[piece] = -1; } PieceCode[WN] = 0; PieceCode[WB] = 1; PieceCode[WR] = 2; PieceCode[WQ] = 3; PieceCode[BN] = 0; PieceCode[BB] = 1; PieceCode[BR] = 2; PieceCode[BQ] = 3; // PieceDeltaSize[][] & PieceDeltaDelta[][][] for (piece = 0; piece < 4; piece++) { for (delta = 0; delta < 256; delta++) { PieceDeltaSize[piece][delta] = 0; } } for (king = 0; king < SquareNb; king++) { if (SQUARE_IS_OK(king)) { for (from = 0; from < SquareNb; from++) { if (SQUARE_IS_OK(from)) { // knight for (pos = 0; (inc=KnightInc[pos]) != IncNone; pos++) { to = from + inc; if (SQUARE_IS_OK(to) && DISTANCE(to,king) == 1) { add_attack(0,king-from,to-from); } } // bishop for (pos = 0; (inc=BishopInc[pos]) != IncNone; pos++) { for (to = from+inc; SQUARE_IS_OK(to); to += inc) { if (DISTANCE(to,king) == 1) { add_attack(1,king-from,to-from); break; } } } // rook for (pos = 0; (inc=RookInc[pos]) != IncNone; pos++) { for (to = from+inc; SQUARE_IS_OK(to); to += inc) { if (DISTANCE(to,king) == 1) { add_attack(2,king-from,to-from); break; } } } // queen for (pos = 0; (inc=QueenInc[pos]) != IncNone; pos++) { for (to = from+inc; SQUARE_IS_OK(to); to += inc) { if (DISTANCE(to,king) == 1) { add_attack(3,king-from,to-from); break; } } } } } } } for (piece = 0; piece < 4; piece++) { for (delta = 0; delta < 256; delta++) { size = PieceDeltaSize[piece][delta]; ASSERT(size>=0&&size<3); PieceDeltaDelta[piece][delta][size] = DeltaNone; } } } // add_attack() static void add_attack(int piece, int king, int target) { int size; int i; ASSERT(piece>=0&&piece<4); ASSERT(delta_is_ok(king)); ASSERT(delta_is_ok(target)); size = PieceDeltaSize[piece][DeltaOffset+king]; ASSERT(size>=0&&size<3); for (i = 0; i < size; i++) { if (PieceDeltaDelta[piece][DeltaOffset+king][i] == target) return; // already in the table } if (size < 2) { PieceDeltaDelta[piece][DeltaOffset+king][size] = target; size++; PieceDeltaSize[piece][DeltaOffset+king] = size; } } // is_attacked() bool is_attacked(const board_t * board, int to, int colour) { int inc; int pawn; const sq_t * ptr; int from; int piece; int delta; int sq; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(COLOUR_IS_OK(colour)); // pawn attack inc = PAWN_MOVE_INC(colour); pawn = PAWN_MAKE(colour); if (board->square[to-(inc-1)] == pawn) return true; if (board->square[to-(inc+1)] == pawn) return true; // piece attack for (ptr = &board->piece[colour][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; delta = to - from; if (PSEUDO_ATTACK(piece,delta)) { inc = DELTA_INC_ALL(delta); ASSERT(inc!=IncNone); sq = from; do { sq += inc; if (sq == to) return true; } while (board->square[sq] == Empty); } } return false; } // line_is_empty() bool line_is_empty(const board_t * board, int from, int to) { int delta; int inc, sq; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); delta = to - from; ASSERT(delta_is_ok(delta)); inc = DELTA_INC_ALL(delta); ASSERT(inc!=IncNone); sq = from; do { sq += inc; if (sq == to) return true; } while (board->square[sq] == Empty); return false; // blocker } // is_pinned() bool is_pinned(const board_t * board, int square, int colour) { int from, to; int inc; int sq, piece; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(COLOUR_IS_OK(colour)); from = square; to = KING_POS(board,colour); inc = DELTA_INC_LINE(to-from); if (inc == IncNone) return false; // not a line sq = from; do sq += inc; while (board->square[sq] == Empty); if (sq != to) return false; // blocker sq = from; do sq -= inc; while ((piece=board->square[sq]) == Empty); return COLOUR_IS(piece,COLOUR_OPP(colour)) && SLIDER_ATTACK(piece,inc); } // attack_is_ok() bool attack_is_ok(const attack_t * attack) { int i; int sq, inc; if (attack == NULL) return false; // checks if (attack->dn < 0 || attack->dn > 2) return false; for (i = 0; i < attack->dn; i++) { sq = attack->ds[i]; if (!SQUARE_IS_OK(sq)) return false; inc = attack->di[i]; if (inc != IncNone && !inc_is_ok(inc)) return false; } if (attack->ds[attack->dn] != SquareNone) return false; if (attack->di[attack->dn] != IncNone) return false; return true; } // attack_set() void attack_set(attack_t * attack, const board_t * board) { int me, opp; const sq_t * ptr; int from, to; int inc; int pawn; int delta, piece; int sq; ASSERT(attack!=NULL); ASSERT(board!=NULL); // init attack->dn = 0; me = board->turn; opp = COLOUR_OPP(me); to = KING_POS(board,me); // pawn attacks inc = PAWN_MOVE_INC(opp); pawn = PAWN_MAKE(opp); from = to - (inc-1); if (board->square[from] == pawn) { attack->ds[attack->dn] = from; attack->di[attack->dn] = IncNone; attack->dn++; } from = to - (inc+1); if (board->square[from] == pawn) { attack->ds[attack->dn] = from; attack->di[attack->dn] = IncNone; attack->dn++; } // piece attacks for (ptr = &board->piece[opp][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; delta = to - from; ASSERT(delta_is_ok(delta)); if (PSEUDO_ATTACK(piece,delta)) { inc = IncNone; if (PIECE_IS_SLIDER(piece)) { // check for blockers inc = DELTA_INC_LINE(delta); ASSERT(inc!=IncNone); sq = from; do sq += inc; while (board->square[sq] == Empty); if (sq != to) continue; // blocker => next attacker } attack->ds[attack->dn] = from; attack->di[attack->dn] = -inc; // HACK attack->dn++; } } attack->ds[attack->dn] = SquareNone; attack->di[attack->dn] = IncNone; // debug ASSERT(attack_is_ok(attack)); } // piece_attack_king() bool piece_attack_king(const board_t * board, int piece, int from, int king) { int code; const int * delta_ptr; int delta, inc; int to; int sq; ASSERT(board!=NULL); ASSERT(piece_is_ok(piece)); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(king)); code = PieceCode[piece]; ASSERT(code>=0&&code<4); if (PIECE_IS_SLIDER(piece)) { for (delta_ptr = PieceDeltaDelta[code][DeltaOffset+(king-from)]; (delta=*delta_ptr) != DeltaNone; delta_ptr++) { ASSERT(delta_is_ok(delta)); inc = DeltaIncLine[DeltaOffset+delta]; ASSERT(inc!=IncNone); to = from + delta; sq = from; do { sq += inc; // if (sq == to && SQUARE_IS_OK(to)) { // ASSERT(DISTANCE(to,king)==1); // return true; if (DISTANCE(sq,king)<=2 && SQUARE_IS_OK(sq)){ return true; } } while (board->square[sq] == Empty); } } else { // non-slider for (delta_ptr = PieceDeltaDelta[code][DeltaOffset+(king-from)]; (delta=*delta_ptr) != DeltaNone; delta_ptr++) { ASSERT(delta_is_ok(delta)); to = from + delta; if (SQUARE_IS_OK(to)) { ASSERT(DISTANCE(to,king)==1); return true; } } } return false; } // end of attack.cpp toga2-3.0.0.1SE1/src/random.cpp0000644000175000017500000005031411125217322015332 0ustar oliveroliver // random.cpp // includes #include "random.h" #include "util.h" // "constants" const uint64 Random64[RandomNb] = { U64(0x9D39247E33776D41), U64(0x2AF7398005AAA5C7), U64(0x44DB015024623547), U64(0x9C15F73E62A76AE2), U64(0x75834465489C0C89), U64(0x3290AC3A203001BF), U64(0x0FBBAD1F61042279), U64(0xE83A908FF2FB60CA), U64(0x0D7E765D58755C10), U64(0x1A083822CEAFE02D), U64(0x9605D5F0E25EC3B0), U64(0xD021FF5CD13A2ED5), U64(0x40BDF15D4A672E32), U64(0x011355146FD56395), U64(0x5DB4832046F3D9E5), U64(0x239F8B2D7FF719CC), U64(0x05D1A1AE85B49AA1), U64(0x679F848F6E8FC971), U64(0x7449BBFF801FED0B), U64(0x7D11CDB1C3B7ADF0), U64(0x82C7709E781EB7CC), U64(0xF3218F1C9510786C), U64(0x331478F3AF51BBE6), U64(0x4BB38DE5E7219443), U64(0xAA649C6EBCFD50FC), U64(0x8DBD98A352AFD40B), U64(0x87D2074B81D79217), U64(0x19F3C751D3E92AE1), U64(0xB4AB30F062B19ABF), U64(0x7B0500AC42047AC4), U64(0xC9452CA81A09D85D), U64(0x24AA6C514DA27500), U64(0x4C9F34427501B447), U64(0x14A68FD73C910841), U64(0xA71B9B83461CBD93), U64(0x03488B95B0F1850F), U64(0x637B2B34FF93C040), U64(0x09D1BC9A3DD90A94), U64(0x3575668334A1DD3B), U64(0x735E2B97A4C45A23), U64(0x18727070F1BD400B), U64(0x1FCBACD259BF02E7), U64(0xD310A7C2CE9B6555), U64(0xBF983FE0FE5D8244), U64(0x9F74D14F7454A824), U64(0x51EBDC4AB9BA3035), U64(0x5C82C505DB9AB0FA), U64(0xFCF7FE8A3430B241), U64(0x3253A729B9BA3DDE), U64(0x8C74C368081B3075), U64(0xB9BC6C87167C33E7), U64(0x7EF48F2B83024E20), U64(0x11D505D4C351BD7F), U64(0x6568FCA92C76A243), U64(0x4DE0B0F40F32A7B8), U64(0x96D693460CC37E5D), U64(0x42E240CB63689F2F), U64(0x6D2BDCDAE2919661), U64(0x42880B0236E4D951), U64(0x5F0F4A5898171BB6), U64(0x39F890F579F92F88), U64(0x93C5B5F47356388B), U64(0x63DC359D8D231B78), U64(0xEC16CA8AEA98AD76), U64(0x5355F900C2A82DC7), U64(0x07FB9F855A997142), U64(0x5093417AA8A7ED5E), U64(0x7BCBC38DA25A7F3C), U64(0x19FC8A768CF4B6D4), U64(0x637A7780DECFC0D9), U64(0x8249A47AEE0E41F7), U64(0x79AD695501E7D1E8), U64(0x14ACBAF4777D5776), U64(0xF145B6BECCDEA195), U64(0xDABF2AC8201752FC), U64(0x24C3C94DF9C8D3F6), U64(0xBB6E2924F03912EA), U64(0x0CE26C0B95C980D9), U64(0xA49CD132BFBF7CC4), U64(0xE99D662AF4243939), U64(0x27E6AD7891165C3F), U64(0x8535F040B9744FF1), U64(0x54B3F4FA5F40D873), U64(0x72B12C32127FED2B), U64(0xEE954D3C7B411F47), U64(0x9A85AC909A24EAA1), U64(0x70AC4CD9F04F21F5), U64(0xF9B89D3E99A075C2), U64(0x87B3E2B2B5C907B1), U64(0xA366E5B8C54F48B8), U64(0xAE4A9346CC3F7CF2), U64(0x1920C04D47267BBD), U64(0x87BF02C6B49E2AE9), U64(0x092237AC237F3859), U64(0xFF07F64EF8ED14D0), U64(0x8DE8DCA9F03CC54E), U64(0x9C1633264DB49C89), U64(0xB3F22C3D0B0B38ED), U64(0x390E5FB44D01144B), U64(0x5BFEA5B4712768E9), U64(0x1E1032911FA78984), U64(0x9A74ACB964E78CB3), U64(0x4F80F7A035DAFB04), U64(0x6304D09A0B3738C4), U64(0x2171E64683023A08), U64(0x5B9B63EB9CEFF80C), U64(0x506AACF489889342), U64(0x1881AFC9A3A701D6), U64(0x6503080440750644), U64(0xDFD395339CDBF4A7), U64(0xEF927DBCF00C20F2), U64(0x7B32F7D1E03680EC), U64(0xB9FD7620E7316243), U64(0x05A7E8A57DB91B77), U64(0xB5889C6E15630A75), U64(0x4A750A09CE9573F7), U64(0xCF464CEC899A2F8A), U64(0xF538639CE705B824), U64(0x3C79A0FF5580EF7F), U64(0xEDE6C87F8477609D), U64(0x799E81F05BC93F31), U64(0x86536B8CF3428A8C), U64(0x97D7374C60087B73), U64(0xA246637CFF328532), U64(0x043FCAE60CC0EBA0), U64(0x920E449535DD359E), U64(0x70EB093B15B290CC), U64(0x73A1921916591CBD), U64(0x56436C9FE1A1AA8D), U64(0xEFAC4B70633B8F81), U64(0xBB215798D45DF7AF), U64(0x45F20042F24F1768), U64(0x930F80F4E8EB7462), U64(0xFF6712FFCFD75EA1), U64(0xAE623FD67468AA70), U64(0xDD2C5BC84BC8D8FC), U64(0x7EED120D54CF2DD9), U64(0x22FE545401165F1C), U64(0xC91800E98FB99929), U64(0x808BD68E6AC10365), U64(0xDEC468145B7605F6), U64(0x1BEDE3A3AEF53302), U64(0x43539603D6C55602), U64(0xAA969B5C691CCB7A), U64(0xA87832D392EFEE56), U64(0x65942C7B3C7E11AE), U64(0xDED2D633CAD004F6), U64(0x21F08570F420E565), U64(0xB415938D7DA94E3C), U64(0x91B859E59ECB6350), U64(0x10CFF333E0ED804A), U64(0x28AED140BE0BB7DD), U64(0xC5CC1D89724FA456), U64(0x5648F680F11A2741), U64(0x2D255069F0B7DAB3), U64(0x9BC5A38EF729ABD4), U64(0xEF2F054308F6A2BC), U64(0xAF2042F5CC5C2858), U64(0x480412BAB7F5BE2A), U64(0xAEF3AF4A563DFE43), U64(0x19AFE59AE451497F), U64(0x52593803DFF1E840), U64(0xF4F076E65F2CE6F0), U64(0x11379625747D5AF3), U64(0xBCE5D2248682C115), U64(0x9DA4243DE836994F), U64(0x066F70B33FE09017), U64(0x4DC4DE189B671A1C), U64(0x51039AB7712457C3), U64(0xC07A3F80C31FB4B4), U64(0xB46EE9C5E64A6E7C), U64(0xB3819A42ABE61C87), U64(0x21A007933A522A20), U64(0x2DF16F761598AA4F), U64(0x763C4A1371B368FD), U64(0xF793C46702E086A0), U64(0xD7288E012AEB8D31), U64(0xDE336A2A4BC1C44B), U64(0x0BF692B38D079F23), U64(0x2C604A7A177326B3), U64(0x4850E73E03EB6064), U64(0xCFC447F1E53C8E1B), U64(0xB05CA3F564268D99), U64(0x9AE182C8BC9474E8), U64(0xA4FC4BD4FC5558CA), U64(0xE755178D58FC4E76), U64(0x69B97DB1A4C03DFE), U64(0xF9B5B7C4ACC67C96), U64(0xFC6A82D64B8655FB), U64(0x9C684CB6C4D24417), U64(0x8EC97D2917456ED0), U64(0x6703DF9D2924E97E), U64(0xC547F57E42A7444E), U64(0x78E37644E7CAD29E), U64(0xFE9A44E9362F05FA), U64(0x08BD35CC38336615), U64(0x9315E5EB3A129ACE), U64(0x94061B871E04DF75), U64(0xDF1D9F9D784BA010), U64(0x3BBA57B68871B59D), U64(0xD2B7ADEEDED1F73F), U64(0xF7A255D83BC373F8), U64(0xD7F4F2448C0CEB81), U64(0xD95BE88CD210FFA7), U64(0x336F52F8FF4728E7), U64(0xA74049DAC312AC71), U64(0xA2F61BB6E437FDB5), U64(0x4F2A5CB07F6A35B3), U64(0x87D380BDA5BF7859), U64(0x16B9F7E06C453A21), U64(0x7BA2484C8A0FD54E), U64(0xF3A678CAD9A2E38C), U64(0x39B0BF7DDE437BA2), U64(0xFCAF55C1BF8A4424), U64(0x18FCF680573FA594), U64(0x4C0563B89F495AC3), U64(0x40E087931A00930D), U64(0x8CFFA9412EB642C1), U64(0x68CA39053261169F), U64(0x7A1EE967D27579E2), U64(0x9D1D60E5076F5B6F), U64(0x3810E399B6F65BA2), U64(0x32095B6D4AB5F9B1), U64(0x35CAB62109DD038A), U64(0xA90B24499FCFAFB1), U64(0x77A225A07CC2C6BD), U64(0x513E5E634C70E331), U64(0x4361C0CA3F692F12), U64(0xD941ACA44B20A45B), U64(0x528F7C8602C5807B), U64(0x52AB92BEB9613989), U64(0x9D1DFA2EFC557F73), U64(0x722FF175F572C348), U64(0x1D1260A51107FE97), U64(0x7A249A57EC0C9BA2), U64(0x04208FE9E8F7F2D6), U64(0x5A110C6058B920A0), U64(0x0CD9A497658A5698), U64(0x56FD23C8F9715A4C), U64(0x284C847B9D887AAE), U64(0x04FEABFBBDB619CB), U64(0x742E1E651C60BA83), U64(0x9A9632E65904AD3C), U64(0x881B82A13B51B9E2), U64(0x506E6744CD974924), U64(0xB0183DB56FFC6A79), U64(0x0ED9B915C66ED37E), U64(0x5E11E86D5873D484), U64(0xF678647E3519AC6E), U64(0x1B85D488D0F20CC5), U64(0xDAB9FE6525D89021), U64(0x0D151D86ADB73615), U64(0xA865A54EDCC0F019), U64(0x93C42566AEF98FFB), U64(0x99E7AFEABE000731), U64(0x48CBFF086DDF285A), U64(0x7F9B6AF1EBF78BAF), U64(0x58627E1A149BBA21), U64(0x2CD16E2ABD791E33), U64(0xD363EFF5F0977996), U64(0x0CE2A38C344A6EED), U64(0x1A804AADB9CFA741), U64(0x907F30421D78C5DE), U64(0x501F65EDB3034D07), U64(0x37624AE5A48FA6E9), U64(0x957BAF61700CFF4E), U64(0x3A6C27934E31188A), U64(0xD49503536ABCA345), U64(0x088E049589C432E0), U64(0xF943AEE7FEBF21B8), U64(0x6C3B8E3E336139D3), U64(0x364F6FFA464EE52E), U64(0xD60F6DCEDC314222), U64(0x56963B0DCA418FC0), U64(0x16F50EDF91E513AF), U64(0xEF1955914B609F93), U64(0x565601C0364E3228), U64(0xECB53939887E8175), U64(0xBAC7A9A18531294B), U64(0xB344C470397BBA52), U64(0x65D34954DAF3CEBD), U64(0xB4B81B3FA97511E2), U64(0xB422061193D6F6A7), U64(0x071582401C38434D), U64(0x7A13F18BBEDC4FF5), U64(0xBC4097B116C524D2), U64(0x59B97885E2F2EA28), U64(0x99170A5DC3115544), U64(0x6F423357E7C6A9F9), U64(0x325928EE6E6F8794), U64(0xD0E4366228B03343), U64(0x565C31F7DE89EA27), U64(0x30F5611484119414), U64(0xD873DB391292ED4F), U64(0x7BD94E1D8E17DEBC), U64(0xC7D9F16864A76E94), U64(0x947AE053EE56E63C), U64(0xC8C93882F9475F5F), U64(0x3A9BF55BA91F81CA), U64(0xD9A11FBB3D9808E4), U64(0x0FD22063EDC29FCA), U64(0xB3F256D8ACA0B0B9), U64(0xB03031A8B4516E84), U64(0x35DD37D5871448AF), U64(0xE9F6082B05542E4E), U64(0xEBFAFA33D7254B59), U64(0x9255ABB50D532280), U64(0xB9AB4CE57F2D34F3), U64(0x693501D628297551), U64(0xC62C58F97DD949BF), U64(0xCD454F8F19C5126A), U64(0xBBE83F4ECC2BDECB), U64(0xDC842B7E2819E230), U64(0xBA89142E007503B8), U64(0xA3BC941D0A5061CB), U64(0xE9F6760E32CD8021), U64(0x09C7E552BC76492F), U64(0x852F54934DA55CC9), U64(0x8107FCCF064FCF56), U64(0x098954D51FFF6580), U64(0x23B70EDB1955C4BF), U64(0xC330DE426430F69D), U64(0x4715ED43E8A45C0A), U64(0xA8D7E4DAB780A08D), U64(0x0572B974F03CE0BB), U64(0xB57D2E985E1419C7), U64(0xE8D9ECBE2CF3D73F), U64(0x2FE4B17170E59750), U64(0x11317BA87905E790), U64(0x7FBF21EC8A1F45EC), U64(0x1725CABFCB045B00), U64(0x964E915CD5E2B207), U64(0x3E2B8BCBF016D66D), U64(0xBE7444E39328A0AC), U64(0xF85B2B4FBCDE44B7), U64(0x49353FEA39BA63B1), U64(0x1DD01AAFCD53486A), U64(0x1FCA8A92FD719F85), U64(0xFC7C95D827357AFA), U64(0x18A6A990C8B35EBD), U64(0xCCCB7005C6B9C28D), U64(0x3BDBB92C43B17F26), U64(0xAA70B5B4F89695A2), U64(0xE94C39A54A98307F), U64(0xB7A0B174CFF6F36E), U64(0xD4DBA84729AF48AD), U64(0x2E18BC1AD9704A68), U64(0x2DE0966DAF2F8B1C), U64(0xB9C11D5B1E43A07E), U64(0x64972D68DEE33360), U64(0x94628D38D0C20584), U64(0xDBC0D2B6AB90A559), U64(0xD2733C4335C6A72F), U64(0x7E75D99D94A70F4D), U64(0x6CED1983376FA72B), U64(0x97FCAACBF030BC24), U64(0x7B77497B32503B12), U64(0x8547EDDFB81CCB94), U64(0x79999CDFF70902CB), U64(0xCFFE1939438E9B24), U64(0x829626E3892D95D7), U64(0x92FAE24291F2B3F1), U64(0x63E22C147B9C3403), U64(0xC678B6D860284A1C), U64(0x5873888850659AE7), U64(0x0981DCD296A8736D), U64(0x9F65789A6509A440), U64(0x9FF38FED72E9052F), U64(0xE479EE5B9930578C), U64(0xE7F28ECD2D49EECD), U64(0x56C074A581EA17FE), U64(0x5544F7D774B14AEF), U64(0x7B3F0195FC6F290F), U64(0x12153635B2C0CF57), U64(0x7F5126DBBA5E0CA7), U64(0x7A76956C3EAFB413), U64(0x3D5774A11D31AB39), U64(0x8A1B083821F40CB4), U64(0x7B4A38E32537DF62), U64(0x950113646D1D6E03), U64(0x4DA8979A0041E8A9), U64(0x3BC36E078F7515D7), U64(0x5D0A12F27AD310D1), U64(0x7F9D1A2E1EBE1327), U64(0xDA3A361B1C5157B1), U64(0xDCDD7D20903D0C25), U64(0x36833336D068F707), U64(0xCE68341F79893389), U64(0xAB9090168DD05F34), U64(0x43954B3252DC25E5), U64(0xB438C2B67F98E5E9), U64(0x10DCD78E3851A492), U64(0xDBC27AB5447822BF), U64(0x9B3CDB65F82CA382), U64(0xB67B7896167B4C84), U64(0xBFCED1B0048EAC50), U64(0xA9119B60369FFEBD), U64(0x1FFF7AC80904BF45), U64(0xAC12FB171817EEE7), U64(0xAF08DA9177DDA93D), U64(0x1B0CAB936E65C744), U64(0xB559EB1D04E5E932), U64(0xC37B45B3F8D6F2BA), U64(0xC3A9DC228CAAC9E9), U64(0xF3B8B6675A6507FF), U64(0x9FC477DE4ED681DA), U64(0x67378D8ECCEF96CB), U64(0x6DD856D94D259236), U64(0xA319CE15B0B4DB31), U64(0x073973751F12DD5E), U64(0x8A8E849EB32781A5), U64(0xE1925C71285279F5), U64(0x74C04BF1790C0EFE), U64(0x4DDA48153C94938A), U64(0x9D266D6A1CC0542C), U64(0x7440FB816508C4FE), U64(0x13328503DF48229F), U64(0xD6BF7BAEE43CAC40), U64(0x4838D65F6EF6748F), U64(0x1E152328F3318DEA), U64(0x8F8419A348F296BF), U64(0x72C8834A5957B511), U64(0xD7A023A73260B45C), U64(0x94EBC8ABCFB56DAE), U64(0x9FC10D0F989993E0), U64(0xDE68A2355B93CAE6), U64(0xA44CFE79AE538BBE), U64(0x9D1D84FCCE371425), U64(0x51D2B1AB2DDFB636), U64(0x2FD7E4B9E72CD38C), U64(0x65CA5B96B7552210), U64(0xDD69A0D8AB3B546D), U64(0x604D51B25FBF70E2), U64(0x73AA8A564FB7AC9E), U64(0x1A8C1E992B941148), U64(0xAAC40A2703D9BEA0), U64(0x764DBEAE7FA4F3A6), U64(0x1E99B96E70A9BE8B), U64(0x2C5E9DEB57EF4743), U64(0x3A938FEE32D29981), U64(0x26E6DB8FFDF5ADFE), U64(0x469356C504EC9F9D), U64(0xC8763C5B08D1908C), U64(0x3F6C6AF859D80055), U64(0x7F7CC39420A3A545), U64(0x9BFB227EBDF4C5CE), U64(0x89039D79D6FC5C5C), U64(0x8FE88B57305E2AB6), U64(0xA09E8C8C35AB96DE), U64(0xFA7E393983325753), U64(0xD6B6D0ECC617C699), U64(0xDFEA21EA9E7557E3), U64(0xB67C1FA481680AF8), U64(0xCA1E3785A9E724E5), U64(0x1CFC8BED0D681639), U64(0xD18D8549D140CAEA), U64(0x4ED0FE7E9DC91335), U64(0xE4DBF0634473F5D2), U64(0x1761F93A44D5AEFE), U64(0x53898E4C3910DA55), U64(0x734DE8181F6EC39A), U64(0x2680B122BAA28D97), U64(0x298AF231C85BAFAB), U64(0x7983EED3740847D5), U64(0x66C1A2A1A60CD889), U64(0x9E17E49642A3E4C1), U64(0xEDB454E7BADC0805), U64(0x50B704CAB602C329), U64(0x4CC317FB9CDDD023), U64(0x66B4835D9EAFEA22), U64(0x219B97E26FFC81BD), U64(0x261E4E4C0A333A9D), U64(0x1FE2CCA76517DB90), U64(0xD7504DFA8816EDBB), U64(0xB9571FA04DC089C8), U64(0x1DDC0325259B27DE), U64(0xCF3F4688801EB9AA), U64(0xF4F5D05C10CAB243), U64(0x38B6525C21A42B0E), U64(0x36F60E2BA4FA6800), U64(0xEB3593803173E0CE), U64(0x9C4CD6257C5A3603), U64(0xAF0C317D32ADAA8A), U64(0x258E5A80C7204C4B), U64(0x8B889D624D44885D), U64(0xF4D14597E660F855), U64(0xD4347F66EC8941C3), U64(0xE699ED85B0DFB40D), U64(0x2472F6207C2D0484), U64(0xC2A1E7B5B459AEB5), U64(0xAB4F6451CC1D45EC), U64(0x63767572AE3D6174), U64(0xA59E0BD101731A28), U64(0x116D0016CB948F09), U64(0x2CF9C8CA052F6E9F), U64(0x0B090A7560A968E3), U64(0xABEEDDB2DDE06FF1), U64(0x58EFC10B06A2068D), U64(0xC6E57A78FBD986E0), U64(0x2EAB8CA63CE802D7), U64(0x14A195640116F336), U64(0x7C0828DD624EC390), U64(0xD74BBE77E6116AC7), U64(0x804456AF10F5FB53), U64(0xEBE9EA2ADF4321C7), U64(0x03219A39EE587A30), U64(0x49787FEF17AF9924), U64(0xA1E9300CD8520548), U64(0x5B45E522E4B1B4EF), U64(0xB49C3B3995091A36), U64(0xD4490AD526F14431), U64(0x12A8F216AF9418C2), U64(0x001F837CC7350524), U64(0x1877B51E57A764D5), U64(0xA2853B80F17F58EE), U64(0x993E1DE72D36D310), U64(0xB3598080CE64A656), U64(0x252F59CF0D9F04BB), U64(0xD23C8E176D113600), U64(0x1BDA0492E7E4586E), U64(0x21E0BD5026C619BF), U64(0x3B097ADAF088F94E), U64(0x8D14DEDB30BE846E), U64(0xF95CFFA23AF5F6F4), U64(0x3871700761B3F743), U64(0xCA672B91E9E4FA16), U64(0x64C8E531BFF53B55), U64(0x241260ED4AD1E87D), U64(0x106C09B972D2E822), U64(0x7FBA195410E5CA30), U64(0x7884D9BC6CB569D8), U64(0x0647DFEDCD894A29), U64(0x63573FF03E224774), U64(0x4FC8E9560F91B123), U64(0x1DB956E450275779), U64(0xB8D91274B9E9D4FB), U64(0xA2EBEE47E2FBFCE1), U64(0xD9F1F30CCD97FB09), U64(0xEFED53D75FD64E6B), U64(0x2E6D02C36017F67F), U64(0xA9AA4D20DB084E9B), U64(0xB64BE8D8B25396C1), U64(0x70CB6AF7C2D5BCF0), U64(0x98F076A4F7A2322E), U64(0xBF84470805E69B5F), U64(0x94C3251F06F90CF3), U64(0x3E003E616A6591E9), U64(0xB925A6CD0421AFF3), U64(0x61BDD1307C66E300), U64(0xBF8D5108E27E0D48), U64(0x240AB57A8B888B20), U64(0xFC87614BAF287E07), U64(0xEF02CDD06FFDB432), U64(0xA1082C0466DF6C0A), U64(0x8215E577001332C8), U64(0xD39BB9C3A48DB6CF), U64(0x2738259634305C14), U64(0x61CF4F94C97DF93D), U64(0x1B6BACA2AE4E125B), U64(0x758F450C88572E0B), U64(0x959F587D507A8359), U64(0xB063E962E045F54D), U64(0x60E8ED72C0DFF5D1), U64(0x7B64978555326F9F), U64(0xFD080D236DA814BA), U64(0x8C90FD9B083F4558), U64(0x106F72FE81E2C590), U64(0x7976033A39F7D952), U64(0xA4EC0132764CA04B), U64(0x733EA705FAE4FA77), U64(0xB4D8F77BC3E56167), U64(0x9E21F4F903B33FD9), U64(0x9D765E419FB69F6D), U64(0xD30C088BA61EA5EF), U64(0x5D94337FBFAF7F5B), U64(0x1A4E4822EB4D7A59), U64(0x6FFE73E81B637FB3), U64(0xDDF957BC36D8B9CA), U64(0x64D0E29EEA8838B3), U64(0x08DD9BDFD96B9F63), U64(0x087E79E5A57D1D13), U64(0xE328E230E3E2B3FB), U64(0x1C2559E30F0946BE), U64(0x720BF5F26F4D2EAA), U64(0xB0774D261CC609DB), U64(0x443F64EC5A371195), U64(0x4112CF68649A260E), U64(0xD813F2FAB7F5C5CA), U64(0x660D3257380841EE), U64(0x59AC2C7873F910A3), U64(0xE846963877671A17), U64(0x93B633ABFA3469F8), U64(0xC0C0F5A60EF4CDCF), U64(0xCAF21ECD4377B28C), U64(0x57277707199B8175), U64(0x506C11B9D90E8B1D), U64(0xD83CC2687A19255F), U64(0x4A29C6465A314CD1), U64(0xED2DF21216235097), U64(0xB5635C95FF7296E2), U64(0x22AF003AB672E811), U64(0x52E762596BF68235), U64(0x9AEBA33AC6ECC6B0), U64(0x944F6DE09134DFB6), U64(0x6C47BEC883A7DE39), U64(0x6AD047C430A12104), U64(0xA5B1CFDBA0AB4067), U64(0x7C45D833AFF07862), U64(0x5092EF950A16DA0B), U64(0x9338E69C052B8E7B), U64(0x455A4B4CFE30E3F5), U64(0x6B02E63195AD0CF8), U64(0x6B17B224BAD6BF27), U64(0xD1E0CCD25BB9C169), U64(0xDE0C89A556B9AE70), U64(0x50065E535A213CF6), U64(0x9C1169FA2777B874), U64(0x78EDEFD694AF1EED), U64(0x6DC93D9526A50E68), U64(0xEE97F453F06791ED), U64(0x32AB0EDB696703D3), U64(0x3A6853C7E70757A7), U64(0x31865CED6120F37D), U64(0x67FEF95D92607890), U64(0x1F2B1D1F15F6DC9C), U64(0xB69E38A8965C6B65), U64(0xAA9119FF184CCCF4), U64(0xF43C732873F24C13), U64(0xFB4A3D794A9A80D2), U64(0x3550C2321FD6109C), U64(0x371F77E76BB8417E), U64(0x6BFA9AAE5EC05779), U64(0xCD04F3FF001A4778), U64(0xE3273522064480CA), U64(0x9F91508BFFCFC14A), U64(0x049A7F41061A9E60), U64(0xFCB6BE43A9F2FE9B), U64(0x08DE8A1C7797DA9B), U64(0x8F9887E6078735A1), U64(0xB5B4071DBFC73A66), U64(0x230E343DFBA08D33), U64(0x43ED7F5A0FAE657D), U64(0x3A88A0FBBCB05C63), U64(0x21874B8B4D2DBC4F), U64(0x1BDEA12E35F6A8C9), U64(0x53C065C6C8E63528), U64(0xE34A1D250E7A8D6B), U64(0xD6B04D3B7651DD7E), U64(0x5E90277E7CB39E2D), U64(0x2C046F22062DC67D), U64(0xB10BB459132D0A26), U64(0x3FA9DDFB67E2F199), U64(0x0E09B88E1914F7AF), U64(0x10E8B35AF3EEAB37), U64(0x9EEDECA8E272B933), U64(0xD4C718BC4AE8AE5F), U64(0x81536D601170FC20), U64(0x91B534F885818A06), U64(0xEC8177F83F900978), U64(0x190E714FADA5156E), U64(0xB592BF39B0364963), U64(0x89C350C893AE7DC1), U64(0xAC042E70F8B383F2), U64(0xB49B52E587A1EE60), U64(0xFB152FE3FF26DA89), U64(0x3E666E6F69AE2C15), U64(0x3B544EBE544C19F9), U64(0xE805A1E290CF2456), U64(0x24B33C9D7ED25117), U64(0xE74733427B72F0C1), U64(0x0A804D18B7097475), U64(0x57E3306D881EDB4F), U64(0x4AE7D6A36EB5DBCB), U64(0x2D8D5432157064C8), U64(0xD1E649DE1E7F268B), U64(0x8A328A1CEDFE552C), U64(0x07A3AEC79624C7DA), U64(0x84547DDC3E203C94), U64(0x990A98FD5071D263), U64(0x1A4FF12616EEFC89), U64(0xF6F7FD1431714200), U64(0x30C05B1BA332F41C), U64(0x8D2636B81555A786), U64(0x46C9FEB55D120902), U64(0xCCEC0A73B49C9921), U64(0x4E9D2827355FC492), U64(0x19EBB029435DCB0F), U64(0x4659D2B743848A2C), U64(0x963EF2C96B33BE31), U64(0x74F85198B05A2E7D), U64(0x5A0F544DD2B1FB18), U64(0x03727073C2E134B1), U64(0xC7F6AA2DE59AEA61), U64(0x352787BAA0D7C22F), U64(0x9853EAB63B5E0B35), U64(0xABBDCDD7ED5C0860), U64(0xCF05DAF5AC8D77B0), U64(0x49CAD48CEBF4A71E), U64(0x7A4C10EC2158C4A6), U64(0xD9E92AA246BF719E), U64(0x13AE978D09FE5557), U64(0x730499AF921549FF), U64(0x4E4B705B92903BA4), U64(0xFF577222C14F0A3A), U64(0x55B6344CF97AAFAE), U64(0xB862225B055B6960), U64(0xCAC09AFBDDD2CDB4), U64(0xDAF8E9829FE96B5F), U64(0xB5FDFC5D3132C498), U64(0x310CB380DB6F7503), U64(0xE87FBB46217A360E), U64(0x2102AE466EBB1148), U64(0xF8549E1A3AA5E00D), U64(0x07A69AFDCC42261A), U64(0xC4C118BFE78FEAAE), U64(0xF9F4892ED96BD438), U64(0x1AF3DBE25D8F45DA), U64(0xF5B4B0B0D2DEEEB4), U64(0x962ACEEFA82E1C84), U64(0x046E3ECAAF453CE9), U64(0xF05D129681949A4C), U64(0x964781CE734B3C84), U64(0x9C2ED44081CE5FBD), U64(0x522E23F3925E319E), U64(0x177E00F9FC32F791), U64(0x2BC60A63A6F3B3F2), U64(0x222BBFAE61725606), U64(0x486289DDCC3D6780), U64(0x7DC7785B8EFDFC80), U64(0x8AF38731C02BA980), U64(0x1FAB64EA29A2DDF7), U64(0xE4D9429322CD065A), U64(0x9DA058C67844F20C), U64(0x24C0E332B70019B0), U64(0x233003B5A6CFE6AD), U64(0xD586BD01C5C217F6), U64(0x5E5637885F29BC2B), U64(0x7EBA726D8C94094B), U64(0x0A56A5F0BFE39272), U64(0xD79476A84EE20D06), U64(0x9E4C1269BAA4BF37), U64(0x17EFEE45B0DEE640), U64(0x1D95B0A5FCF90BC6), U64(0x93CBE0B699C2585D), U64(0x65FA4F227A2B6D79), U64(0xD5F9E858292504D5), U64(0xC2B5A03F71471A6F), U64(0x59300222B4561E00), U64(0xCE2F8642CA0712DC), U64(0x7CA9723FBB2E8988), U64(0x2785338347F2BA08), U64(0xC61BB3A141E50E8C), U64(0x150F361DAB9DEC26), U64(0x9F6A419D382595F4), U64(0x64A53DC924FE7AC9), U64(0x142DE49FFF7A7C3D), U64(0x0C335248857FA9E7), U64(0x0A9C32D5EAE45305), U64(0xE6C42178C4BBB92E), U64(0x71F1CE2490D20B07), U64(0xF1BCC3D275AFE51A), U64(0xE728E8C83C334074), U64(0x96FBF83A12884624), U64(0x81A1549FD6573DA5), U64(0x5FA7867CAF35E149), U64(0x56986E2EF3ED091B), U64(0x917F1DD5F8886C61), U64(0xD20D8C88C8FFE65F), U64(0x31D71DCE64B2C310), U64(0xF165B587DF898190), U64(0xA57E6339DD2CF3A0), U64(0x1EF6E6DBB1961EC9), U64(0x70CC73D90BC26E24), U64(0xE21A6B35DF0C3AD7), U64(0x003A93D8B2806962), U64(0x1C99DED33CB890A1), U64(0xCF3145DE0ADD4289), U64(0xD0E4427A5514FB72), U64(0x77C621CC9FB3A483), U64(0x67A34DAC4356550B), U64(0xF8D626AAAF278509), }; // functions // random_init() void random_init() { if ((Random64[RandomNb-1] >> 32) != 0xF8D626AA) { // upper half of the last element of the array my_fatal("broken 64-bit types\n"); } } // end of random.cpp toga2-3.0.0.1SE1/src/protocol.h0000644000175000017500000000104511125217314015356 0ustar oliveroliver // protocol.h #ifdef _WIN32 #include #else #include #endif #ifndef PROTOCOL_H #define PROTOCOL_H // includes #include "util.h" // variables #ifdef _WIN32 extern CRITICAL_SECTION CriticalSection; #else extern pthread_mutex_t CriticalSection; #endif // functions extern void loop (); extern void event (); extern void book_parameter(); extern void get (char string[], int size); extern void send (const char format[], ...); #endif // !defined PROTOCOL_H // end of protocol.h toga2-3.0.0.1SE1/src/pawn.cpp0000644000175000017500000003115711125217314015024 0ustar oliveroliver // pawn.cpp // includes #include #include "board.h" #include "colour.h" #include "hash.h" #include "option.h" #include "pawn.h" #include "piece.h" #include "protocol.h" #include "square.h" #include "util.h" #include "search.h" // constants static const bool UseTable = true; static const uint32 TableSize = 16384; // was 16384 256kB tried 65536 // types typedef pawn_info_t entry_t; struct pawn_t { entry_t * table; uint32 size; uint32 mask; uint32 used; sint64 read_nb; sint64 read_hit; sint64 write_nb; sint64 write_collision; }; // constants and variables static /* const */ int PawnStructureWeight = 256; // 100% static const int DoubledOpening = 10; static const int DoubledEndgame = 20; static const int IsolatedOpening = 10; static const int IsolatedOpeningOpen = 20; static const int IsolatedEndgame = 20; static const int BackwardOpening = 8; static const int BackwardOpeningOpen = 16; static const int BackwardEndgame = 10; static const int CandidateOpeningMin = 5; static const int CandidateOpeningMax = 55; static const int CandidateEndgameMin = 10; static const int CandidateEndgameMax = 110; // this was moved to eval.cpp /* static const int PassedOpeningMin = 10; static const int PassedOpeningMax = 70; static const int PassedEndgameMin = 20; static const int PassedEndgameMax = 140; */ static /* const */ int Bonus[RankNb]; // variables int BitEQ[16]; int BitLT[16]; int BitLE[16]; int BitGT[16]; int BitGE[16]; int BitFirst[0x100]; int BitLast[0x100]; int BitCount[0x100]; int BitRev[0x100]; static pawn_t Pawn[MaxThreads][1]; static int BitRank1[RankNb]; static int BitRank2[RankNb]; static int BitRank3[RankNb]; // prototypes static void pawn_comp_info (pawn_info_t * info, const board_t * board); // functions // pawn_init_bit() void pawn_init_bit() { int rank; int first, last, count; int b, rev; // rank-indexed Bit*[] for (rank = 0; rank < RankNb; rank++) { BitEQ[rank] = 0; BitLT[rank] = 0; BitLE[rank] = 0; BitGT[rank] = 0; BitGE[rank] = 0; BitRank1[rank] = 0; BitRank2[rank] = 0; BitRank3[rank] = 0; } for (rank = Rank1; rank <= Rank8; rank++) { BitEQ[rank] = 1 << (rank - Rank1); BitLT[rank] = BitEQ[rank] - 1; BitLE[rank] = BitLT[rank] | BitEQ[rank]; BitGT[rank] = BitLE[rank] ^ 0xFF; BitGE[rank] = BitGT[rank] | BitEQ[rank]; } for (rank = Rank1; rank <= Rank8; rank++) { BitRank1[rank] = BitEQ[rank+1]; BitRank2[rank] = BitEQ[rank+1] | BitEQ[rank+2]; BitRank3[rank] = BitEQ[rank+1] | BitEQ[rank+2] | BitEQ[rank+3]; } // bit-indexed Bit*[] for (b = 0; b < 0x100; b++) { first = Rank8; // HACK for pawn shelter last = Rank1; // HACK count = 0; rev = 0; for (rank = Rank1; rank <= Rank8; rank++) { if ((b & BitEQ[rank]) != 0) { if (rank < first) first = rank; if (rank > last) last = rank; count++; rev |= BitEQ[RANK_OPP(rank)]; } } BitFirst[b] = first; BitLast[b] = last; BitCount[b] = count; BitRev[b] = rev; } } // pawn_parameter() void pawn_parameter() { // UCI options PawnStructureWeight = (option_get_int("Pawn Structure") * 256 + 50) / 100; } // pawn_init() void pawn_init() { int rank, ThreadId; // UCI options pawn_parameter(); // bonus for (rank = 0; rank < RankNb; rank++) Bonus[rank] = 0; Bonus[Rank4] = 26; Bonus[Rank5] = 77; Bonus[Rank6] = 154; Bonus[Rank7] = 256; // pawn hash-table for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ Pawn[ThreadId]->size = 0; Pawn[ThreadId]->mask = 0; Pawn[ThreadId]->table = NULL; } } // pawn_alloc() void pawn_alloc() { int ThreadId; ASSERT(sizeof(entry_t)==16); if (UseTable) { for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ Pawn[ThreadId]->size = TableSize; Pawn[ThreadId]->mask = TableSize - 1; Pawn[ThreadId]->table = (entry_t *) my_malloc(Pawn[ThreadId]->size*sizeof(entry_t)); pawn_clear(ThreadId); } } } // pawn_free() void pawn_free() { int ThreadId; ASSERT(sizeof(entry_t)==16); if (UseTable) { for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ my_free(Pawn[ThreadId]->table); } } } // pawn_clear() void pawn_clear(int ThreadId) { if (Pawn[ThreadId]->table != NULL) { memset(Pawn[ThreadId]->table,0,Pawn[ThreadId]->size*sizeof(entry_t)); } Pawn[ThreadId]->used = 0; Pawn[ThreadId]->read_nb = 0; Pawn[ThreadId]->read_hit = 0; Pawn[ThreadId]->write_nb = 0; Pawn[ThreadId]->write_collision = 0; } // pawn_get_info() void pawn_get_info(pawn_info_t * info, const board_t * board, int ThreadId) { uint64 key; entry_t * entry; ASSERT(info!=NULL); ASSERT(board!=NULL); // probe if (UseTable) { Pawn[ThreadId]->read_nb++; key = board->pawn_key; entry = &Pawn[ThreadId]->table[KEY_INDEX(key)&Pawn[ThreadId]->mask]; if (entry->lock == KEY_LOCK(key)) { // found Pawn[ThreadId]->read_hit++; *info = *entry; return; } } // calculation pawn_comp_info(info,board); // store if (UseTable) { Pawn[ThreadId]->write_nb++; if (entry->lock == 0) { // HACK: assume free entry Pawn[ThreadId]->used++; } else { Pawn[ThreadId]->write_collision++; } *entry = *info; entry->lock = KEY_LOCK(key); } } // pawn_comp_info() static void pawn_comp_info(pawn_info_t * info, const board_t * board) { int colour; int file, rank; int me, opp; const sq_t * ptr; int sq; bool backward, candidate, doubled, isolated, open, passed; int t1, t2; int n; int bits; int opening[ColourNb], endgame[ColourNb]; int flags[ColourNb]; int file_bits[ColourNb]; int passed_bits[ColourNb]; int single_file[ColourNb]; ASSERT(info!=NULL); ASSERT(board!=NULL); // pawn_file[] #if DEBUG for (colour = 0; colour < ColourNb; colour++) { int pawn_file[FileNb]; me = colour; for (file = 0; file < FileNb; file++) { pawn_file[file] = 0; } for (ptr = &board->pawn[me][0]; (sq=*ptr) != SquareNone; ptr++) { file = SQUARE_FILE(sq); rank = PAWN_RANK(sq,me); ASSERT(file>=FileA&&file<=FileH); ASSERT(rank>=Rank2&&rank<=Rank7); pawn_file[file] |= BIT(rank); } for (file = 0; file < FileNb; file++) { if (board->pawn_file[colour][file] != pawn_file[file]) my_fatal("board->pawn_file[][]\n"); } } #endif // init for (colour = 0; colour < ColourNb; colour++) { opening[colour] = 0; endgame[colour] = 0; flags[colour] = 0; file_bits[colour] = 0; passed_bits[colour] = 0; single_file[colour] = SquareNone; } // features and scoring for (colour = 0; colour < ColourNb; colour++) { me = colour; opp = COLOUR_OPP(me); for (ptr = &board->pawn[me][0]; (sq=*ptr) != SquareNone; ptr++) { // init file = SQUARE_FILE(sq); rank = PAWN_RANK(sq,me); ASSERT(file>=FileA&&file<=FileH); ASSERT(rank>=Rank2&&rank<=Rank7); // flags file_bits[me] |= BIT(file); if (rank == Rank2) flags[me] |= BackRankFlag; // features backward = false; candidate = false; doubled = false; isolated = false; open = false; passed = false; t1 = board->pawn_file[me][file-1] | board->pawn_file[me][file+1]; t2 = board->pawn_file[me][file] | BitRev[board->pawn_file[opp][file]]; // doubled if ((board->pawn_file[me][file] & BitLT[rank]) != 0) { doubled = true; } // isolated and backward if (t1 == 0) { isolated = true; } else if ((t1 & BitLE[rank]) == 0) { backward = true; // really backward? if ((t1 & BitRank1[rank]) != 0) { ASSERT(rank+2<=Rank8); if (((t2 & BitRank1[rank]) | ((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitRank2[rank])) == 0) { backward = false; } } else if (rank == Rank2 && ((t1 & BitEQ[rank+2]) != 0)) { ASSERT(rank+3<=Rank8); if (((t2 & BitRank2[rank]) | ((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitRank3[rank])) == 0) { backward = false; } } } // open, candidate and passed if ((t2 & BitGT[rank]) == 0) { open = true; if (((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitGT[rank]) == 0) { passed = true; passed_bits[me] |= BIT(file); } else { // candidate? n = 0; n += BIT_COUNT(board->pawn_file[me][file-1]&BitLE[rank]); n += BIT_COUNT(board->pawn_file[me][file+1]&BitLE[rank]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file-1]]&BitGT[rank]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file+1]]&BitGT[rank]); if (n >= 0) { // safe? n = 0; n += BIT_COUNT(board->pawn_file[me][file-1]&BitEQ[rank-1]); n += BIT_COUNT(board->pawn_file[me][file+1]&BitEQ[rank-1]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file-1]]&BitEQ[rank+1]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file+1]]&BitEQ[rank+1]); if (n >= 0) candidate = true; } } } // score if (doubled) { opening[me] -= DoubledOpening; endgame[me] -= DoubledEndgame; } if (isolated) { if (open) { opening[me] -= IsolatedOpeningOpen; endgame[me] -= IsolatedEndgame; } else { opening[me] -= IsolatedOpening; endgame[me] -= IsolatedEndgame; } } if (backward) { if (open) { opening[me] -= BackwardOpeningOpen; endgame[me] -= BackwardEndgame; } else { opening[me] -= BackwardOpening; endgame[me] -= BackwardEndgame; } } if (candidate) { opening[me] += quad(CandidateOpeningMin,CandidateOpeningMax,rank); endgame[me] += quad(CandidateEndgameMin,CandidateEndgameMax,rank); } // this was moved to the dynamic evaluation /* if (passed) { opening[me] += quad(PassedOpeningMin,PassedOpeningMax,rank); endgame[me] += quad(PassedEndgameMin,PassedEndgameMax,rank); } */ } } // store info info->opening = ((opening[White] - opening[Black]) * PawnStructureWeight) / 256; info->endgame = ((endgame[White] - endgame[Black]) * PawnStructureWeight) / 256; for (colour = 0; colour < ColourNb; colour++) { me = colour; opp = COLOUR_OPP(me); // draw flags bits = file_bits[me]; if (bits != 0 && (bits & (bits-1)) == 0) { // one set bit file = BIT_FIRST(bits); rank = BIT_FIRST(board->pawn_file[me][file]); ASSERT(rank>=Rank2); if (((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitGT[rank]) == 0) { rank = BIT_LAST(board->pawn_file[me][file]); single_file[me] = SQUARE_MAKE(file,rank); } } info->flags[colour] = flags[colour]; info->passed_bits[colour] = passed_bits[colour]; info->single_file[colour] = single_file[colour]; } } // quad() int quad(int y_min, int y_max, int x) { int y; ASSERT(y_min>=0&&y_min<=y_max&&y_max<=+32767); ASSERT(x>=Rank2&&x<=Rank7); y = y_min + ((y_max - y_min) * Bonus[x] + 128) / 256; ASSERT(y>=y_min&&y<=y_max); return y; } // end of pawn.cpp toga2-3.0.0.1SE1/src/trans.cpp0000644000175000017500000002136412120154350015201 0ustar oliveroliver // trans.cpp // includes #include "hash.h" #include "move.h" #include "option.h" #include "protocol.h" #include "trans.h" #include "util.h" #include "value.h" // macros #define MIN(a,b) ((a)<=(b)?(a):(b)) #define MAX(a,b) ((a)>=(b)?(a):(b)) #define ENTRY_DATE(entry) ((entry)->date_flags>>4) #define ENTRY_FLAGS(entry) ((entry)->date_flags&TransFlags) // constants static const bool UseModulo = false; static const int DateSize = 16; static const int ClusterSize = 4; // TODO: unsigned? static const bool AlwaysWrite = true; //was true static const bool SmartMove = true; static const bool SmartValue = false; static const bool SmartReplace = true; static const int DepthNone = -128; // types /*struct entry_t { uint32 lock; uint16 move; sint8 depth; uint8 date; sint8 move_depth; uint8 flags; sint8 min_depth; sint8 max_depth; sint16 min_value; sint16 max_value; };*/ /*struct entry_t { uint64 key; uint16 move; uint8 depth; uint8 date_flags; sint16 value; uint16 nproc; };*/ struct trans { // HACK: typedef'ed in trans.h entry_t * table; uint32 size; uint32 mask; int date; int age[DateSize]; uint32 used; sint64 read_nb; sint64 read_hit; sint64 write_nb; sint64 write_hit; sint64 write_collision; }; // variables trans_t Trans[1]; // prototypes static void trans_set_date (trans_t * trans, int date); static int trans_age (const trans_t * trans, int date); static entry_t * trans_entry (trans_t * trans, uint64 key); static bool entry_is_ok (const entry_t * entry); // functions // trans_is_ok() bool trans_is_ok(const trans_t * trans) { int date; if (trans == NULL) return false; if (trans->table == NULL) return false; if (trans->size == 0) return false; if (trans->mask == 0 || trans->mask >= trans->size) return false; if (trans->date >= DateSize) return false; for (date = 0; date < DateSize; date++) { if (trans->age[date] != trans_age(trans,date)) return false; } return true; } // trans_init() void trans_init(trans_t * trans) { ASSERT(trans!=NULL); ASSERT(sizeof(entry_t)==16); trans->size = 0; trans->mask = 0; trans->table = NULL; trans_set_date(trans,0); trans_clear(trans); // ASSERT(trans_is_ok(trans)); } // trans_alloc() void trans_alloc(trans_t * trans) { uint32 size, target; ASSERT(trans!=NULL); // calculate size target = option_get_int("Hash"); if (target < 4) target = 128; target *= 1024 * 1024; for (size = 1; size != 0 && size <= target; size *= 2) ; size /= 2; ASSERT(size>0&&size<=target); // allocate table size /= sizeof(entry_t); ASSERT(size!=0&&(size&(size-1))==0); // power of 2 trans->size = size + (ClusterSize - 1); // HACK to avoid testing for end of table trans->mask = size - 1; trans->table = (entry_t *) my_malloc(trans->size*sizeof(entry_t)); trans_clear(trans); ASSERT(trans_is_ok(trans)); } // trans_free() void trans_free(trans_t * trans) { ASSERT(trans_is_ok(trans)); my_free(trans->table); trans->table = NULL; trans->size = 0; trans->mask = 0; } // trans_clear() void trans_clear(trans_t * trans) { entry_t clear_entry[1]; entry_t * entry; uint32 index; ASSERT(trans!=NULL); trans_set_date(trans,0); clear_entry->key = 0; clear_entry->move = MoveNone; clear_entry->depth = DepthNone; clear_entry->date_flags = (trans->date << 4); ASSERT(entry_is_ok(clear_entry)); entry = trans->table; for (index = 0; index < trans->size; index++) { *entry++ = *clear_entry; } } // trans_inc_date() void trans_inc_date(trans_t * trans) { ASSERT(trans!=NULL); trans_set_date(trans,(trans->date+1)%DateSize); } // trans_set_date() static void trans_set_date(trans_t * trans, int date) { ASSERT(trans!=NULL); ASSERT(date>=0&&datedate = date; for (date = 0; date < DateSize; date++) { trans->age[date] = trans_age(trans,date); } trans->used = 0; trans->read_nb = 0; trans->read_hit = 0; trans->write_nb = 0; trans->write_hit = 0; trans->write_collision = 0; } // trans_age() static int trans_age(const trans_t * trans, int date) { int age; ASSERT(trans!=NULL); ASSERT(date>=0&&datedate - date; if (age < 0) age += DateSize; ASSERT(age>=0&&age=0&&move<65536); ASSERT(depth>=0&&depth<256); ASSERT((flags&~TransFlags)==0); ASSERT(value>=-32767&&value<=+32767); // init trans->write_nb++; // probe best_entry = NULL; best_score = -32767; entry = trans_entry(trans,key); for (i = 0; i < ClusterSize; i++, entry++) { if (entry->key == key) { // hash hit => update existing entry trans->write_hit++; if (ENTRY_DATE(entry) != trans->date) trans->used++; if (entry->depth <= depth) { if (SmartMove && move == MoveNone) move = entry->move; if (SmartValue && entry->depth == depth && entry->value == value) { flags |= ENTRY_FLAGS(entry); // HACK } ASSERT(entry->key==key); entry->move = move; entry->depth = depth; entry->date_flags = (trans->date << 4) | flags; entry->value = value; //entry->size = node_nb; // TODO: 64->16 mapping } else { // deeper entry if (SmartMove && entry->move == MoveNone) entry->move = move; entry->date_flags = (trans->date << 4) | ENTRY_FLAGS(entry); } return; } // evaluate replacement score score = trans->age[ENTRY_DATE(entry)] * 256 - entry->depth; if (SmartReplace) score = score * 4 - ENTRY_FLAGS(entry); ASSERT(score>-32767); if (score > best_score) { best_entry = entry; best_score = score; } } // "best" entry found entry = best_entry; ASSERT(entry!=NULL); ASSERT(entry->key!=key); if (ENTRY_DATE(entry) == trans->date) { trans->write_collision++; if (!AlwaysWrite && entry->depth > depth) { return; // do not replace deeper entries } } else { trans->used++; } // store ASSERT(entry!=NULL); entry->key = key; entry->move = move; entry->depth = depth; entry->date_flags = (trans->date << 4) | flags; entry->value = value; // entry->size = node_nb; // TODO: 64->16 mapping } // trans_retrieve() bool trans_retrieve(trans_t * trans, entry_t ** found_entry, uint64 key, int * move, int * depth, int * flags, int * value) { int i; entry_t * entry; ASSERT(trans_is_ok(trans)); ASSERT(move!=NULL); ASSERT(depth!=NULL); ASSERT(flags!=NULL); ASSERT(value!=NULL); // init trans->read_nb++; // probe entry = trans_entry(trans,key); for (i = 0; i < ClusterSize; i++, entry++) { if (entry->key == key) { // found trans->read_hit++; *move = entry->move; *depth = entry->depth; *flags = ENTRY_FLAGS(entry); *value = entry->value; *found_entry = entry; return true; } } // not found *found_entry = entry; return false; } // trans_stats() void trans_stats(const trans_t * trans) { double full; // double hit, collision; ASSERT(trans_is_ok(trans)); full = double(trans->used) / double(trans->size); // hit = double(trans->read_hit) / double(trans->read_nb); // collision = double(trans->write_collision) / double(trans->write_nb); send("info hashfull %.0f",full*1000.0); } // trans_entry() static entry_t * trans_entry(trans_t * trans, uint64 key) { uint32 index; ASSERT(trans_is_ok(trans)); if (UseModulo) { index = key % (trans->mask + 1); } else { index = key & trans->mask; } ASSERT(index<=trans->mask); return &trans->table[index]; } // entry_is_ok() static bool entry_is_ok(const entry_t * entry) { if (entry == NULL) return false; if (ENTRY_DATE(entry) >= DateSize) return false; if (entry->move == MoveNone) return false; return true; } // end of trans.cpp toga2-3.0.0.1SE1/src/main.cpp0000644000175000017500000000266012120130702014767 0ustar oliveroliver // main.cpp // includes #include #include #include "attack.h" #include "book.h" #include "hash.h" #include "move_do.h" #include "option.h" #include "pawn.h" #include "piece.h" #include "protocol.h" #include "random.h" #include "square.h" #include "trans.h" #include "util.h" #include "value.h" #include "vector.h" #include "probe.h" static char * egbb_path = "c:/egbb/"; static uint32 egbb_cache_size = 16; // functions // main() int main(int argc, char * argv[]) { // init util_init(); my_random_init(); // for opening book printf("Toga II 3.0 UCI based on Fruit 2.1 by Thomas Gaksch, Fabien Letouzey and Jerry Donald. Settings by Dieter Eberle\n"); printf("Code was based on Toga II 1.4.1SE by Thomas Gaksch and Chris Formula, with bugfixes by Michel van den Bergh\n"); // early initialisation (the rest is done after UCI options are parsed in protocol.cpp) option_init(); square_init(); piece_init(); pawn_init_bit(); value_init(); vector_init(); attack_init(); move_do_init(); random_init(); hash_init(); trans_init(Trans); book_init(); egbb_cache_size = (egbb_cache_size * 1024 * 1024); egbb_is_loaded = LoadEgbbLibrary(egbb_path,egbb_cache_size); if (!egbb_is_loaded) printf("EgbbProbe not Loaded!\n"); // loop loop(); return EXIT_SUCCESS; } // end of main.cpp toga2-3.0.0.1SE1/src/list.h0000644000175000017500000000214111125217322014465 0ustar oliveroliver // list.h #ifndef LIST_H #define LIST_H // includes #include "board.h" #include "util.h" // constants const int ListSize = 256; // macros #define LIST_CLEAR(list) ((list)->size=0) #define LIST_ADD(list,mv) ((list)->move[(list)->size++]=(mv)) #define LIST_IS_EMPTY(list) ((list)->size==0) #define LIST_SIZE(list) ((list)->size) #define LIST_MOVE(list,pos) ((list)->move[pos]) #define LIST_VALUE(list,pos) ((list)->value[pos]) // types struct list_t { int size; uint16 move[ListSize]; sint16 value[ListSize]; }; typedef bool (*move_test_t) (int move, board_t * board); // functions extern bool list_is_ok (const list_t * list); extern void list_remove (list_t * list, int pos); extern void list_copy (list_t * dst, const list_t * src); extern void list_sort (list_t * list); extern bool list_contain (const list_t * list, int move); extern void list_note (list_t * list); extern void list_filter (list_t * list, board_t * board, move_test_t test, bool keep); #endif // !defined LIST_H // end of list.h toga2-3.0.0.1SE1/src/option.cpp0000644000175000017500000001277612120154356015377 0ustar oliveroliver // option.cpp // includes #include #include "option.h" #include "protocol.h" #include "util.h" // types struct option_t { const char * var; bool declare; const char * init; const char * type; const char * extra; const char * val; }; // variables static option_t Option[] = { { "Hash", true, "128", "spin", "min 4 max 1024", NULL }, // JAS // search X seconds for the best move, equal to "go movetime" { "Search Time", true, "0", "spin", "min 0 max 3600", NULL }, // search X plies deep, equal to "go depth" { "Search Depth", true, "0", "spin", "min 0 max 20", NULL }, // JAS end { "Ponder", true, "false", "check", "", NULL }, { "OwnBook", true, "true", "check", "", NULL }, { "BookFile", true, "performance.bin", "string", "", NULL }, { "Bitbases Path", true, "c:/egbb/", "string", "", NULL }, { "Bitbases Cache Size", true, "16", "spin", "min 16 max 1024", NULL }, { "MultiPV", true, "1", "spin", "min 1 max 10", NULL }, { "NullMove Pruning", true, "Always", "combo", "var Always var Fail High var Never", NULL }, { "NullMove Reduction", true, "3", "spin", "min 1 max 4", NULL }, { "Verification Search", true, "Always", "combo", "var Always var Endgame var Never", NULL }, { "Verification Reduction", true, "5", "spin", "min 1 max 6", NULL }, { "History Pruning", true, "true", "check", "", NULL }, { "History Threshold", true, "70", "spin", "min 0 max 100", NULL }, { "Futility Pruning", true, "true", "check", "", NULL }, { "Futility Margin", true, "100", "spin", "min 0 max 500", NULL }, { "Extended Futility Margin", true, "200", "spin", "min 0 max 900", NULL }, { "Delta Pruning", true, "true", "check", "", NULL }, { "Delta Margin", true, "50", "spin", "min 0 max 500", NULL }, { "Quiescence Check Plies", true, "1", "spin", "min 0 max 2", NULL }, { "Material", true, "100", "spin", "min 0 max 400", NULL }, { "Piece Activity", true, "100", "spin", "min 0 max 400", NULL }, { "Piece Square Activity", true, "100", "spin", "min 0 max 400", NULL }, { "King Safety", true, "100", "spin", "min 0 max 400", NULL }, { "Pawn Structure", true, "100", "spin", "min 0 max 400", NULL }, { "Passed Pawns", true, "100", "spin", "min 0 max 400", NULL }, { "Toga Lazy Eval", true, "true", "check", "", NULL }, { "Toga Lazy Eval Margin", true, "200", "spin", "min 0 max 900", NULL }, { "Toga Lazy Eval Mobility Margin", true, "125", "spin", "min 0 max 900", NULL }, { "Toga Exchange Bonus", false, "20", "spin", "min 0 max 100", NULL }, //{ "Toga King Safety", true, "false", "check", "", NULL }, //{ "Toga King Safety Margin", true, "1700", "spin", "min 500 max 3000", NULL }, //{ "Toga Extended History Pruning",true, "false", "check", "", NULL }, //{ "Toga History Threshold", false, "40", "spin", "min 0 max 100", NULL }, { "Toga King Pawn Endgame Bonus", true, "30", "spin", "min 0 max 100", NULL }, { "Toga Rook Pawn Endgame Penalty", true, "10", "spin", "min 0 max 100", NULL }, { "Number of Threads", true, "1", "spin", "min 1 max 16", NULL }, { NULL, false, NULL, NULL, NULL, NULL, }, }; // prototypes static option_t * option_find (const char var[]); // functions // option_init() void option_init() { option_t * opt; for (opt = &Option[0]; opt->var != NULL; opt++) { option_set(opt->var,opt->init); } } // option_list() void option_list() { option_t * opt; for (opt = &Option[0]; opt->var != NULL; opt++) { if (opt->declare) { if (opt->extra != NULL && *opt->extra != '\0') { send("option name %s type %s default %s %s",opt->var,opt->type,opt->val,opt->extra); } else { send("option name %s type %s default %s",opt->var,opt->type,opt->val); } } } } // option_set() bool option_set(const char var[], const char val[]) { option_t * opt; ASSERT(var!=NULL); ASSERT(val!=NULL); opt = option_find(var); if (opt == NULL) return false; my_string_set(&opt->val,val); return true; } // option_get() const char * option_get(const char var[]) { option_t * opt; ASSERT(var!=NULL); opt = option_find(var); if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",var); return opt->val; } // option_get_bool() bool option_get_bool(const char var[]) { const char * val; val = option_get(var); if (false) { } else if (my_string_equal(val,"true") || my_string_equal(val,"yes") || my_string_equal(val,"1")) { return true; } else if (my_string_equal(val,"false") || my_string_equal(val,"no") || my_string_equal(val,"0")) { return false; } ASSERT(false); return false; } // option_get_int() int option_get_int(const char var[]) { const char * val; val = option_get(var); return atoi(val); } // option_get_string() const char * option_get_string(const char var[]) { const char * val; val = option_get(var); return val; } // option_find() static option_t * option_find(const char var[]) { option_t * opt; ASSERT(var!=NULL); for (opt = &Option[0]; opt->var != NULL; opt++) { if (my_string_equal(opt->var,var)) return opt; } return NULL; } // end of option.cpp toga2-3.0.0.1SE1/src/COPYING0000644000175000017500000004311011125217324014377 0ustar oliveroliver GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. toga2-3.0.0.1SE1/src/Makefile0000644000175000017500000000212011125233030014770 0ustar oliveroliver # files EXE = toga2 OBJS = attack.o board.o book.o eval.o fen.o hash.o list.o main.o material.o \ move.o move_check.o move_do.o move_evasion.o move_gen.o move_legal.o \ option.o pawn.o piece.o posix.o protocol.o pst.o pv.o random.o recog.o \ search.o search_full.o see.o sort.o square.o trans.o util.o value.o \ vector.o probe.o # rules all: $(EXE) .depend clean: $(RM) *.o .depend gmon.out toga2 toga2.intel *~ # general CXX = g++ CXXFLAGS = -pipe LDFLAGS = -lm LDFLAGS += -ldl -lpthread # C++ CXXFLAGS += -O3 -fno-exceptions -fno-rtti -Wall #CXXFLAGS += -mno-cygwin -D_WIN32 -D_MSC_VER # optimisation CXXFLAGS += -fstrict-aliasing CXXFLAGS += -fomit-frame-pointer # CXXFLAGS += -march=athlon-xp # SELECT ME # CXXFLAGS += -march=pentium4 # profiling #CXXFLAGS += -fprofile-generate #LDFLAGS += -fprofile-generate #CXXFLAGS += -fprofile-use # strip LDFLAGS += -s # dependencies $(EXE): $(OBJS) $(CXX) $(LDFLAGS) -o $@ $(OBJS) .depend: $(CXX) -MM $(OBJS:.o=.cpp) > $@ include .depend toga2-3.0.0.1SE1/src/material.h0000644000175000017500000000260211125217320015310 0ustar oliveroliver // material.h #ifndef MATERIAL_H #define MATERIAL_H // includes #include "board.h" #include "colour.h" #include "util.h" // constants enum mat_dummy_t { MAT_NONE, MAT_KK, MAT_KBK, MAT_KKB, MAT_KNK, MAT_KKN, MAT_KPK, MAT_KKP, MAT_KQKQ, MAT_KQKP, MAT_KPKQ, MAT_KRKR, MAT_KRKP, MAT_KPKR, MAT_KBKB, MAT_KBKP, MAT_KPKB, MAT_KBPK, MAT_KKBP, MAT_KNKN, MAT_KNKP, MAT_KPKN, MAT_KNPK, MAT_KKNP, MAT_KRPKR, MAT_KRKRP, MAT_KBPKB, MAT_KBKBP, MAT_NB }; const int DrawNodeFlag = 1 << 0; const int DrawBishopFlag = 1 << 1; const int MatRookPawnFlag = 1 << 0; const int MatBishopFlag = 1 << 1; const int MatKnightFlag = 1 << 2; const int MatKingFlag = 1 << 3; // types struct material_info_t { uint32 lock; uint8 recog; uint8 flags; uint8 cflags[ColourNb]; uint8 mul[ColourNb]; sint16 phase; sint16 opening; sint16 endgame; //int wt; /* Thomas */ //int bt; //sint16 pv[ColourNb]; /* Material without pawn and king */ }; // functions extern void material_init (); extern void material_parameter(); extern void material_alloc (); extern void material_free (); extern void material_clear (int ThreadId); extern void material_get_info (material_info_t * info, const board_t * board, int ThreadId); #endif // !defined MATERIAL_H // end of material.h toga2-3.0.0.1SE1/src/move_do.h0000644000175000017500000000152411125217320015144 0ustar oliveroliver // move_do.h #ifndef MOVE_DO_H #define MOVE_DO_H // includes #include "board.h" #include "util.h" // types struct undo_t { bool capture; int capture_square; int capture_piece; int capture_pos; int pawn_pos; int turn; int flags; int ep_square; int ply_nb; int cap_sq; int moving_piece; int opening; int endgame; uint64 key; uint64 pawn_key; uint64 material_key; }; // functions extern void move_do_init (); extern void move_do (board_t * board, int move, undo_t * undo); extern void move_undo (board_t * board, int move, const undo_t * undo); extern void move_do_null (board_t * board, undo_t * undo); extern void move_undo_null (board_t * board, const undo_t * undo); #endif // !defined MOVE_DO_H // end of move_do.h toga2-3.0.0.1SE1/src/board.cpp0000644000175000017500000003041011125217316015137 0ustar oliveroliver // board.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "fen.h" #include "hash.h" #include "list.h" #include "move.h" #include "move_do.h" #include "move_evasion.h" #include "move_gen.h" #include "move_legal.h" #include "pawn.h" // TODO: bit.h #include "piece.h" #include "pst.h" #include "util.h" #include "value.h" // constants static const bool UseSlowDebug = false; // functions // board_is_ok() bool board_is_ok(const board_t * board) { int sq, piece, colour; int size, pos; if (board == NULL) return false; // optional heavy DEBUG mode if (!UseSlowDebug) return true; // squares for (sq = 0; sq < SquareNb; sq++) { piece = board->square[sq]; pos = board->pos[sq]; if (SQUARE_IS_OK(sq)) { // inside square if (piece == Empty) { if (pos != -1) return false; } else { if (!piece_is_ok(piece)) return false; if (!PIECE_IS_PAWN(piece)) { colour = PIECE_COLOUR(piece); if (pos < 0 || pos >= board->piece_size[colour]) return false; if (board->piece[colour][pos] != sq) return false; } else { // pawn if (SQUARE_IS_PROMOTE(sq)) return false; colour = PIECE_COLOUR(piece); if (pos < 0 || pos >= board->pawn_size[colour]) return false; if (board->pawn[colour][pos] != sq) return false; } } } else { // edge square if (piece != Edge) return false; if (pos != -1) return false; } } // piece lists for (colour = 0; colour < ColourNb; colour++) { // piece list size = board->piece_size[colour]; if (size < 1 || size > 16) return false; for (pos = 0; pos < size; pos++) { sq = board->piece[colour][pos]; if (!SQUARE_IS_OK(sq)) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!COLOUR_IS(piece,colour)) return false; if (pos == 0 && !PIECE_IS_KING(piece)) return false; if (pos != 0 && PIECE_IS_KING(piece)) return false; if (pos != 0 && PIECE_ORDER(piece) > PIECE_ORDER(board->square[board->piece[colour][pos-1]])) { return false; } } sq = board->piece[colour][size]; if (sq != SquareNone) return false; // pawn list size = board->pawn_size[colour]; if (size < 0 || size > 8) return false; for (pos = 0; pos < size; pos++) { sq = board->pawn[colour][pos]; if (!SQUARE_IS_OK(sq)) return false; if (SQUARE_IS_PROMOTE(sq)) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!COLOUR_IS(piece,colour)) return false; if (!PIECE_IS_PAWN(piece)) return false; } sq = board->pawn[colour][size]; if (sq != SquareNone) return false; // piece total if (board->piece_size[colour] + board->pawn_size[colour] > 16) return false; } // material if (board->piece_nb != board->piece_size[White] + board->pawn_size[White] + board->piece_size[Black] + board->pawn_size[Black]) { return false; } if (board->number[WhitePawn12] != board->pawn_size[White]) return false; if (board->number[BlackPawn12] != board->pawn_size[Black]) return false; if (board->number[WhiteKing12] != 1) return false; if (board->number[BlackKing12] != 1) return false; // misc if (!COLOUR_IS_OK(board->turn)) return false; if (board->ply_nb < 0) return false; if (board->sp < board->ply_nb) return false; if (board->cap_sq != SquareNone && !SQUARE_IS_OK(board->cap_sq)) return false; if (board->opening != board_opening(board)) return false; if (board->endgame != board_endgame(board)) return false; if (board->key != hash_key(board)) return false; if (board->pawn_key != hash_pawn_key(board)) return false; if (board->material_key != hash_material_key(board)) return false; return true; } // board_clear() void board_clear(board_t * board) { int sq, sq_64; ASSERT(board!=NULL); // edge squares for (sq = 0; sq < SquareNb; sq++) { board->square[sq] = Edge; } // empty squares for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = SQUARE_FROM_64(sq_64); board->square[sq] = Empty; } // misc board->turn = ColourNone; board->flags = FlagsNone; board->ep_square = SquareNone; board->ply_nb = 0; } // board_copy() void board_copy(board_t * dst, const board_t * src) { ASSERT(dst!=NULL); ASSERT(board_is_ok(src)); *dst = *src; } // board_init_list() void board_init_list(board_t * board) { int sq_64, sq, piece; int colour, pos; int i, size; int square; int order; int file; ASSERT(board!=NULL); // init for (sq = 0; sq < SquareNb; sq++) { board->pos[sq] = -1; } board->piece_nb = 0; for (piece = 0; piece < 12; piece++) board->number[piece] = 0; // piece lists for (colour = 0; colour < ColourNb; colour++) { // piece list pos = 0; board->piece_material[colour] = 0; // Thomas for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = SQUARE_FROM_64(sq_64); piece = board->square[sq]; if (piece != Empty && !piece_is_ok(piece)) my_fatal("board_init_list(): illegal position\n"); if (COLOUR_IS(piece,colour) && !PIECE_IS_PAWN(piece)) { if (pos >= 16) my_fatal("board_init_list(): illegal position\n"); ASSERT(pos>=0&&pos<16); board->pos[sq] = pos; board->piece[colour][pos] = sq; pos++; board->piece_nb++; board->number[PIECE_TO_12(piece)]++; if (piece != WK && piece != BK) // Thomas board->piece_material[colour] += VALUE_PIECE(piece); } } if (board->number[COLOUR_IS_WHITE(colour)?WhiteKing12:BlackKing12] != 1) my_fatal("board_init_list(): illegal position\n"); if (board->number[WhiteBishop12] >= 10) printf("illegal position!\n"); ASSERT(pos>=1&&pos<=16); board->piece[colour][pos] = SquareNone; board->piece_size[colour] = pos; // MV sort size = board->piece_size[colour]; for (i = 1; i < size; i++) { square = board->piece[colour][i]; piece = board->square[square]; order = PIECE_ORDER(piece); for (pos = i; pos > 0 && order > PIECE_ORDER(board->square[(sq=board->piece[colour][pos-1])]); pos--) { ASSERT(pos>0&&pospiece[colour][pos] = sq; ASSERT(board->pos[sq]==pos-1); board->pos[sq] = pos; } ASSERT(pos>=0&&pospiece[colour][pos] = square; ASSERT(board->pos[square]==i); board->pos[square] = pos; } // debug if (DEBUG) { for (i = 0; i < board->piece_size[colour]; i++) { sq = board->piece[colour][i]; ASSERT(board->pos[sq]==i); if (i == 0) { // king ASSERT(PIECE_IS_KING(board->square[sq])); } else { ASSERT(!PIECE_IS_KING(board->square[sq])); ASSERT(PIECE_ORDER(board->square[board->piece[colour][i]])<=PIECE_ORDER(board->square[board->piece[colour][i-1]])); } } } // pawn list for (file = 0; file < FileNb; file++) { board->pawn_file[colour][file] = 0; } pos = 0; for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = SQUARE_FROM_64(sq_64); piece = board->square[sq]; if (COLOUR_IS(piece,colour) && PIECE_IS_PAWN(piece)) { if (pos >= 8 || SQUARE_IS_PROMOTE(sq)) my_fatal("board_init_list(): illegal position\n"); ASSERT(pos>=0&&pos<8); board->pos[sq] = pos; board->pawn[colour][pos] = sq; pos++; board->piece_nb++; board->number[PIECE_TO_12(piece)]++; board->pawn_file[colour][SQUARE_FILE(sq)] |= BIT(PAWN_RANK(sq,colour)); board->piece_material[colour] += VALUE_PIECE(piece); // Thomas } } ASSERT(pos>=0&&pos<=8); board->pawn[colour][pos] = SquareNone; board->pawn_size[colour] = pos; if (board->piece_size[colour] + board->pawn_size[colour] > 16) my_fatal("board_init_list(): illegal position\n"); } // last square board->cap_sq = SquareNone; board->moving_piece = PieceNone256; // PST board->opening = board_opening(board); board->endgame = board_endgame(board); // hash key for (i = 0; i < board->ply_nb; i++) board->stack[i] = 0; // HACK board->sp = board->ply_nb; board->key = hash_key(board); board->pawn_key = hash_pawn_key(board); board->material_key = hash_material_key(board); // legality if (!board_is_legal(board)) my_fatal("board_init_list(): illegal position\n"); // debug ASSERT(board_is_ok(board)); } // board_is_legal() bool board_is_legal(const board_t * board) { ASSERT(board!=NULL); return !IS_IN_CHECK(board,COLOUR_OPP(board->turn)); } // board_is_check() bool board_is_check(const board_t * board) { ASSERT(board!=NULL); return IS_IN_CHECK(board,board->turn); } // board_is_mate() bool board_is_mate(const board_t * board) { attack_t attack[1]; ASSERT(board!=NULL); attack_set(attack,board); if (!ATTACK_IN_CHECK(attack)) return false; // not in check => not mate if (legal_evasion_exist(board,attack)) return false; // legal move => not mate return true; // in check and no legal move => mate } // board_is_stalemate() bool board_is_stalemate(board_t * board) { list_t list[1]; int i, move; ASSERT(board!=NULL); // init if (IS_IN_CHECK(board,board->turn)) return false; // in check => not stalemate // move loop gen_moves(list,board); for (i = 0; i < LIST_SIZE(list); i++) { move = LIST_MOVE(list,i); if (pseudo_is_legal(move,board)) return false; // legal move => not stalemate } return true; // in check and no legal move => mate } // board_is_repetition() bool board_is_repetition(const board_t * board) { int i; ASSERT(board!=NULL); // 50-move rule if (board->ply_nb >= 100) { // potential draw if (board->ply_nb > 100) return true; ASSERT(board->ply_nb==100); return !board_is_mate(board); } // position repetition ASSERT(board->sp>=board->ply_nb); for (i = 4; i <= board->ply_nb; i += 2) { if (board->stack[board->sp-i] == board->key) return true; } return false; } // board_opening() int board_opening(const board_t * board) { int opening; int colour; const sq_t * ptr; int sq, piece; ASSERT(board!=NULL); opening = 0; for (colour = 0; colour < ColourNb; colour++) { for (ptr = &board->piece[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; opening += PST(PIECE_TO_12(piece),SQUARE_TO_64(sq),Opening); } for (ptr = &board->pawn[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; opening += PST(PIECE_TO_12(piece),SQUARE_TO_64(sq),Opening); } } return opening; } // board_endgame() int board_endgame(const board_t * board) { int endgame; int colour; const sq_t * ptr; int sq, piece; ASSERT(board!=NULL); endgame = 0; for (colour = 0; colour < ColourNb; colour++) { for (ptr = &board->piece[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; endgame += PST(PIECE_TO_12(piece),SQUARE_TO_64(sq),Endgame); } for (ptr = &board->pawn[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; endgame += PST(PIECE_TO_12(piece),SQUARE_TO_64(sq),Endgame); } } return endgame; } // end of board.cpp toga2-3.0.0.1SE1/src/hash.h0000644000175000017500000000162111125217314014440 0ustar oliveroliver // hash.h #ifndef HASH_H #define HASH_H // includes #include "board.h" #include "util.h" // macros #define KEY_INDEX(key) ((uint32)(key)) #define KEY_LOCK(key) ((uint32)((key)>>32)) // constants const int RandomPiece = 0; // 12 * 64 const int RandomCastle = 768; // 4 const int RandomEnPassant = 772; // 8 const int RandomTurn = 780; // 1 // variables extern uint64 Castle64[16]; // functions extern void hash_init (); extern uint64 hash_key (const board_t * board); extern uint64 hash_pawn_key (const board_t * board); extern uint64 hash_material_key (const board_t * board); extern uint64 hash_piece_key (int piece, int square); extern uint64 hash_castle_key (int flags); extern uint64 hash_ep_key (int square); extern uint64 hash_turn_key (int colour); #endif // !defined HASH_H // end of hash.h toga2-3.0.0.1SE1/src/move_evasion.cpp0000644000175000017500000001563011125217322016546 0ustar oliveroliver // move_evasion.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "list.h" #include "move.h" #include "move_evasion.h" #include "move_gen.h" #include "piece.h" #include "util.h" // prototypes static bool gen_evasions (list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop); static bool add_pawn_moves (list_t * list, const board_t * board, int to, bool legal, bool stop); static bool add_pawn_captures (list_t * list, const board_t * board, int to, bool legal, bool stop); static bool add_piece_moves (list_t * list, const board_t * board, int to, bool legal, bool stop); // functions // gen_legal_evasions() void gen_legal_evasions(list_t * list, const board_t * board, const attack_t * attack) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(attack!=NULL); gen_evasions(list,board,attack,true,false); // debug ASSERT(list_is_ok(list)); } // gen_pseudo_evasions() void gen_pseudo_evasions(list_t * list, const board_t * board, const attack_t * attack) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(attack!=NULL); gen_evasions(list,board,attack,false,false); // debug ASSERT(list_is_ok(list)); } // legal_evasion_exist() bool legal_evasion_exist(const board_t * board, const attack_t * attack) { list_t list[1]; // dummy ASSERT(board!=NULL); ASSERT(attack!=NULL); return gen_evasions(list,board,attack,true,true); } // gen_evasions() static bool gen_evasions(list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop) { int me, opp; int opp_flag; int king; const inc_t * inc_ptr; int inc; int to; int piece; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(attack!=NULL); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); ASSERT(board_is_check(board)); ASSERT(ATTACK_IN_CHECK(attack)); // init LIST_CLEAR(list); me = board->turn; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); king = KING_POS(board,me); for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) { if (inc != -attack->di[0] && inc != -attack->di[1]) { // avoid escaping along a check line to = king + inc; piece = board->square[to]; if (piece == Empty || FLAG_IS(piece,opp_flag)) { if (!legal || !is_attacked(board,to,opp)) { if (stop) return true; LIST_ADD(list,MOVE_MAKE(king,to)); } } } } if (attack->dn >= 2) return false; // double check, we are done // single check ASSERT(attack->dn==1); // capture the checking piece if (add_pawn_captures(list,board,attack->ds[0],legal,stop) && stop) return true; if (add_piece_moves(list,board,attack->ds[0],legal,stop) && stop) return true; // interpose a piece inc = attack->di[0]; if (inc != IncNone) { // line for (to = king+inc; to != attack->ds[0]; to += inc) { ASSERT(SQUARE_IS_OK(to)); ASSERT(board->square[to]==Empty); if (add_pawn_moves(list,board,to,legal,stop) && stop) return true; if (add_piece_moves(list,board,to,legal,stop) && stop) return true; } } return false; } // add_pawn_moves() static bool add_pawn_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) { int me; int inc; int pawn; int from; int piece; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); ASSERT(board->square[to]==Empty); me = board->turn; inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); from = to - inc; piece = board->square[from]; if (piece == pawn) { // single push if (!legal || !is_pinned(board,from,me)) { if (stop) return true; add_pawn_move(list,from,to); } } else if (piece == Empty && PAWN_RANK(to,me) == Rank4) { // double push from = to - (2*inc); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } return false; } // add_pawn_captures() static bool add_pawn_captures(list_t * list, const board_t * board, int to, bool legal, bool stop) { int me; int inc; int pawn; int from; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(board->turn))); me = board->turn; inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); from = to - (inc-1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; add_pawn_move(list,from,to); } } from = to - (inc+1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; add_pawn_move(list,from,to); } } if (board->ep_square != SquareNone && to == SQUARE_EP_DUAL(board->ep_square)) { ASSERT(PAWN_RANK(to,me)==Rank5); ASSERT(PIECE_IS_PAWN(board->square[to])); to = board->ep_square; ASSERT(PAWN_RANK(to,me)==Rank6); ASSERT(board->square[to]==Empty); from = to - (inc-1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } } from = to - (inc+1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } } } return false; } // add_piece_moves() static bool add_piece_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) { int me; const sq_t * ptr; int from, piece; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); me = board->turn; for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; if (PIECE_ATTACK(board,piece,from,to)) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; LIST_ADD(list,MOVE_MAKE(from,to)); } } } return false; } // end of move_evasion.cpp toga2-3.0.0.1SE1/src/toga.sh0000644000175000017500000000017511345441374014646 0ustar oliveroliverrm *.o icc -o toga *.cpp -w -Ot -march=pentiumpro -DNDEBUG -D_MSC_VER -D_LINUX -lm -static -unroll -vec -ipo -prof_use toga2-3.0.0.1SE1/src/recog.cpp0000644000175000017500000001313211125217320015144 0ustar oliveroliver // recog.cpp // includes #include "board.h" #include "colour.h" #include "material.h" #include "piece.h" #include "recog.h" #include "util.h" #include "vector.h" // prototypes static bool kpk_draw (int wp, int wk, int bk, int turn); static bool kbpk_draw (int wp, int wb, int bk); // functions // recog_draw() bool recog_draw(const board_t * board, int ThreadId) { material_info_t mat_info[1]; ASSERT(board!=NULL); // material if (board->piece_nb > 4) return false; material_get_info(mat_info,board,ThreadId); if ((mat_info->flags & DrawNodeFlag) == 0) return false; // recognisers if (false) { } else if (mat_info->recog == MAT_KK) { // KK return true; } else if (mat_info->recog == MAT_KBK) { // KBK (white) return true; } else if (mat_info->recog == MAT_KKB) { // KBK (black) return true; } else if (mat_info->recog == MAT_KNK) { // KNK (white) return true; } else if (mat_info->recog == MAT_KKN) { // KNK (black) return true; } else if (mat_info->recog == MAT_KPK) { // KPK (white) int me, opp; int wp, wk, bk; me = White; opp = COLOUR_OPP(me); wp = board->pawn[me][0]; wk = KING_POS(board,me); bk = KING_POS(board,opp); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wk = SQUARE_FILE_MIRROR(wk); bk = SQUARE_FILE_MIRROR(bk); } if (kpk_draw(wp,wk,bk,board->turn)) { return true; } } else if (mat_info->recog == MAT_KKP) { // KPK (black) int me, opp; int wp, wk, bk; me = Black; opp = COLOUR_OPP(me); wp = SQUARE_RANK_MIRROR(board->pawn[me][0]); wk = SQUARE_RANK_MIRROR(KING_POS(board,me)); bk = SQUARE_RANK_MIRROR(KING_POS(board,opp)); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wk = SQUARE_FILE_MIRROR(wk); bk = SQUARE_FILE_MIRROR(bk); } if (kpk_draw(wp,wk,bk,COLOUR_OPP(board->turn))) { return true; } } else if (mat_info->recog == MAT_KBKB) { // KBKB int wb, bb; wb = board->piece[White][1]; bb = board->piece[Black][1]; if (SQUARE_COLOUR(wb) == SQUARE_COLOUR(bb)) { // bishops on same colour return true; } } else if (mat_info->recog == MAT_KBPK) { // KBPK (white) int me, opp; int wp, wb, bk; me = White; opp = COLOUR_OPP(me); wp = board->pawn[me][0]; wb = board->piece[me][1]; bk = KING_POS(board,opp); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wb = SQUARE_FILE_MIRROR(wb); bk = SQUARE_FILE_MIRROR(bk); } if (kbpk_draw(wp,wb,bk)) return true; } else if (mat_info->recog == MAT_KKBP) { // KBPK (black) int me, opp; int wp, wb, bk; me = Black; opp = COLOUR_OPP(me); wp = SQUARE_RANK_MIRROR(board->pawn[me][0]); wb = SQUARE_RANK_MIRROR(board->piece[me][1]); bk = SQUARE_RANK_MIRROR(KING_POS(board,opp)); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wb = SQUARE_FILE_MIRROR(wb); bk = SQUARE_FILE_MIRROR(bk); } if (kbpk_draw(wp,wb,bk)) return true; } else { ASSERT(false); } return false; } // kpk_draw() static bool kpk_draw(int wp, int wk, int bk, int turn) { int wp_file, wp_rank; int wk_file; int bk_file, bk_rank; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_IS_OK(wk)); ASSERT(SQUARE_IS_OK(bk)); ASSERT(COLOUR_IS_OK(turn)); ASSERT(SQUARE_FILE(wp)<=FileD); wp_file = SQUARE_FILE(wp); wp_rank = SQUARE_RANK(wp); wk_file = SQUARE_FILE(wk); bk_file = SQUARE_FILE(bk); bk_rank = SQUARE_RANK(bk); if (false) { } else if (bk == wp+16) { if (wp_rank <= Rank6) { return true; } else { ASSERT(wp_rank==Rank7); if (COLOUR_IS_WHITE(turn)) { if (wk == wp-15 || wk == wp-17) return true; } else { if (wk != wp-15 && wk != wp-17) return true; } } } else if (bk == wp+32) { if (wp_rank <= Rank5) { return true; } else { ASSERT(wp_rank==Rank6); if (COLOUR_IS_WHITE(turn)) { if (wk != wp-1 && wk != wp+1) return true; } else { return true; } } } else if (wk == wp-1 || wk == wp+1) { if (bk == wk+32 && COLOUR_IS_WHITE(turn)) { // opposition return true; } } else if (wk == wp+15 || wk == wp+16 || wk == wp+17) { if (wp_rank <= Rank4) { if (bk == wk+32 && COLOUR_IS_WHITE(turn)) { // opposition return true; } } } // rook pawn if (wp_file == FileA) { if (DISTANCE(bk,A8) <= 1) return true; if (wk_file == FileA) { if (wp_rank == Rank2) wp_rank++; // HACK if (bk_file == FileC && bk_rank > wp_rank) return true; } } return false; } // kbpk_draw() static bool kbpk_draw (int wp, int wb, int bk) { ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_IS_OK(wb)); ASSERT(SQUARE_IS_OK(bk)); if (SQUARE_FILE(wp) == FileA && DISTANCE(bk,A8) <= 1 && SQUARE_COLOUR(wb) != SQUARE_COLOUR(A8)) { return true; } return false; } // end of recog.cpp toga2-3.0.0.1SE1/src/eval.h0000644000175000017500000000052511125217320014443 0ustar oliveroliver // eval.h #ifndef EVAL_H #define EVAL_H // includes #include "board.h" #include "util.h" extern bool egbb_is_loaded; // functions extern void eval_init (); extern void eval_parameter (); extern int eval (board_t * board, int alpha, int beta, int ThreadId); #endif // !defined EVAL_H // end of eval.h toga2-3.0.0.1SE1/src/protocol.cpp0000644000175000017500000003716512120130760015720 0ustar oliveroliver // protocol.cpp // includes #include #include #include #include #ifdef _WIN32 #include #endif #include "board.h" #include "book.h" #include "eval.h" #include "fen.h" #include "material.h" #include "move.h" #include "move_do.h" #include "move_legal.h" #include "option.h" #include "pawn.h" #include "posix.h" #include "protocol.h" #include "pst.h" #include "search.h" #include "trans.h" #include "util.h" //#include "sort.h" #include "probe.h" // constants #define VERSION "3.0" static const double NormalRatio = 1.0; static const double PonderRatio = 1.25; // variables #ifdef _WIN32 CRITICAL_SECTION CriticalSection; #else pthread_mutex_t CriticalSection=PTHREAD_MUTEX_INITIALIZER; #endif static bool Init; static bool Searching; // search in progress? static bool Infinite; // infinite or ponder mode? static bool Delay; // postpone "bestmove" in infinite/ponder mode? static char * dirptr = "C:/egbb"; // prototypes static void init (); static void loop_step (); static void parse_go (char string[]); static void parse_position (char string[]); static void parse_setoption (char string[]); static void send_best_move (); static bool string_equal (const char s1[], const char s2[]); static bool string_start_with (const char s1[], const char s2[]); // functions void book_parameter() { // UCI options book_close(); if (option_get_bool("OwnBook")) { book_open(option_get_string("BookFile")); } } // loop() void loop() { // init (to help debugging) Init = false; Searching = false; Infinite = false; Delay = false; search_clear(); board_from_fen(SearchInput->board,StartFen); // loop while (true) loop_step(); } // init() static void init() { if (!Init) { // late initialisation Init = true; NumberThreads=option_get_int("Number of Threads"); if(NumberThreads>MaxThreads) NumberThreads=MaxThreads; book_parameter(); //SearchInput->multipv = option_get_int("MultiPV"); trans_alloc(Trans); pawn_init(); pawn_alloc(); material_init(); material_alloc(); pst_init(); eval_init(); #ifdef _WIN32 InitializeCriticalSection(&CriticalSection); #endif SearchInput->exit_engine = false; start_suspend_threads(); } } // event() void event() { while (!SearchInfo[0]->stop && input_available()) loop_step(); } // loop_step() static void loop_step() { char string[65536]; int ThreadId; // read a line get(string,65536); /* FILE *fp; fp=fopen("toga.log","a+"); fprintf(fp,"%s\n",string); fclose(fp); */ // parse if (false) { } else if (string_start_with(string,"debug ")) { // dummy } else if (string_start_with(string,"go ")) { if (!Searching && !Delay) { init(); parse_go(string); } else { ASSERT(false); } } else if (string_equal(string,"isready")) { if (!Searching && !Delay) { init(); } send("readyok"); // no need to wait when searching (dixit SMK) } else if (string_equal(string,"ponderhit")) { if (Searching) { ASSERT(Infinite); SearchInput->infinite = false; Infinite = false; } else if (Delay) { send_best_move(); Delay = false; } else { ASSERT(false); } } else if (string_start_with(string,"position ")) { if (!Searching && !Delay) { init(); parse_position(string); } else { ASSERT(false); } } else if (string_equal(string,"quit")) { ASSERT(!Searching); ASSERT(!Delay); SearchInput->exit_engine = true; resume_threads(); exit(EXIT_SUCCESS); } else if (string_start_with(string,"setoption ")) { if (!Searching && !Delay) { parse_setoption(string); pawn_parameter(); material_parameter(); book_parameter(); pst_init(); eval_parameter(); } else { ASSERT(false); } } else if (string_equal(string,"stop")) { if (Searching) { for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ SearchInfo[ThreadId]->stop = true; } Infinite = false; } else if (Delay) { send_best_move(); Delay = false; } } else if (string_equal(string,"uci")) { ASSERT(!Searching); ASSERT(!Delay); send("id name Toga II " VERSION); send("id author Thomas Gaksch and Fabien Letouzey"); option_list(); send("uciok"); } else if (string_equal(string,"ucinewgame")) { if (!Searching && !Delay && Init) { trans_clear(Trans); } else { ASSERT(false); } } } // parse_go() static void parse_go(char string[]) { const char * ptr; bool infinite, ponder; int depth, mate, movestogo; sint64 nodes; double binc, btime, movetime, winc, wtime; double time, inc; double time_max, alloc; int ThreadId; // init infinite = false; ponder = false; depth = -1; mate = -1; movestogo = -1; nodes = -1; binc = -1.0; btime = -1.0; movetime = -1.0; winc = -1.0; wtime = -1.0; // parse ptr = strtok(string," "); // skip "go" for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) { if (false) { } else if (string_equal(ptr,"binc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); binc = double(atoi(ptr)) / 1000.0; ASSERT(binc>=0.0); } else if (string_equal(ptr,"btime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); btime = double(atoi(ptr)) / 1000.0; ASSERT(btime>=0.0); } else if (string_equal(ptr,"depth")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); depth = atoi(ptr); ASSERT(depth>=0); } else if (string_equal(ptr,"infinite")) { infinite = true; } else if (string_equal(ptr,"mate")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); mate = atoi(ptr); ASSERT(mate>=0); } else if (string_equal(ptr,"movestogo")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movestogo = atoi(ptr); ASSERT(movestogo>=0); } else if (string_equal(ptr,"movetime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movetime = double(atoi(ptr)) / 1000.0; ASSERT(movetime>=0.0); } else if (string_equal(ptr,"nodes")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); nodes = my_atoll(ptr); ASSERT(nodes>=0); } else if (string_equal(ptr,"ponder")) { ponder = true; } else if (string_equal(ptr,"searchmoves")) { // dummy } else if (string_equal(ptr,"winc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); winc = double(atoi(ptr)) / 1000.0; ASSERT(winc>=0.0); } else if (string_equal(ptr,"wtime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); wtime = double(atoi(ptr)) / 1000.0; ASSERT(wtime>=0.0); } } // init search_clear(); // depth limit // JAS int option_depth = 0; option_depth = option_get_int("Search Depth"); if (option_depth > 0) { depth = option_depth; } // JAS end if (depth >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = depth; } else if (mate >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply } // time limit if (COLOUR_IS_WHITE(SearchInput->board->turn)) { time = wtime; inc = winc; } else { time = btime; inc = binc; } if (movestogo <= 0 || movestogo > 30) movestogo = 30; // HACK was 30 if (inc < 0.0) inc = 0.0; // JAS int option_movetime = 0; option_movetime = option_get_int("Search Time"); if (option_movetime > 0) { movetime = option_movetime; } // JAS end if (movetime >= 0.0) { // fixed time SearchInput->time_is_limited = true; SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit SearchInput->time_limit_2 = movetime; } else if (time >= 0.0) { // dynamic allocation time_max = time * 0.95 - 1.0; if (time_max < 0.0) time_max = 0.0; SearchInput->time_is_limited = true; alloc = (time_max + inc * double(movestogo-1)) / double(movestogo); alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio); if (alloc > time_max) alloc = time_max; SearchInput->time_limit_1 = alloc; alloc = (time_max + inc * double(movestogo-1)) * 0.5; if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1; if (alloc > time_max) alloc = time_max; SearchInput->time_limit_2 = alloc; } if (infinite || ponder) SearchInput->infinite = true; // search ASSERT(!Searching); ASSERT(!Delay); Searching = true; Infinite = infinite || ponder; Delay = false; search(); for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ search_update_current(ThreadId); } ASSERT(Searching); ASSERT(!Delay); Searching = false; Delay = Infinite; if (!Delay) send_best_move(); } // parse_position() static void parse_position(char string[]) { const char * fen; char * moves; const char * ptr; char move_string[256]; int move; undo_t undo[1]; // init fen = strstr(string,"fen "); moves = strstr(string,"moves "); // start position if (fen != NULL) { // "fen" present if (moves != NULL) { // "moves" present ASSERT(moves>fen); moves[-1] = '\0'; // dirty, but so is UCI } board_from_fen(SearchInput->board,fen+4); // CHANGE ME } else { // HACK: assumes startpos board_from_fen(SearchInput->board,StartFen); } // moves if (moves != NULL) { // "moves" present ptr = moves + 6; while (*ptr != '\0') { move_string[0] = *ptr++; move_string[1] = *ptr++; move_string[2] = *ptr++; move_string[3] = *ptr++; if (*ptr == '\0' || *ptr == ' ') { move_string[4] = '\0'; } else { // promote move_string[4] = *ptr++; move_string[5] = '\0'; } move = move_from_string(move_string,SearchInput->board); move_do(SearchInput->board,move,undo); while (*ptr == ' ') ptr++; } } } // parse_setoption() static void parse_setoption(char string[]) { const char * name; char * value; uint32 egbb_cache_size; char * egbb_path; // init name = strstr(string,"name "); value = strstr(string,"value "); if (name == NULL || value == NULL || name >= value) return; // ignore buttons value[-1] = '\0'; // HACK name += 5; value += 6; // update option_set(name,value); // update bitbases if needed if (my_string_equal(name,"Bitbases Path") || my_string_equal(name,"Bitbases Cache Size")){ egbb_cache_size = (option_get_int("Bitbases Cache Size") * 1024 * 1024); egbb_path = (char *) option_get_string("Bitbases Path"); egbb_is_loaded = LoadEgbbLibrary(egbb_path,egbb_cache_size); if (!egbb_is_loaded) printf("EgbbProbe not Loaded!\n"); } // update transposition-table size if needed if (Init && my_string_equal(name,"Hash")) { // Init => already allocated ASSERT(!Searching); if (option_get_int("Hash") >= 4) { trans_free(Trans); trans_alloc(Trans); } } if (Init && my_string_equal(name,"Number of Threads")) { // Init => already started ASSERT(!Searching); if (option_get_int("Number of Threads")!= NumberThreads) { exit_threads(); pawn_free(); material_free(); NumberThreads=option_get_int("Number of Threads"); if(NumberThreads>MaxThreads) NumberThreads=MaxThreads; pawn_alloc(); material_alloc(); search_clear(); start_suspend_threads(); } } } // send_best_move() static void send_best_move() { double time, speed, cpu; sint64 node_nb; char move_string[256]; char ponder_string[256]; int move; int ThreadId, bestThreadId; mv_t * pv; // info // HACK: should be in search.cpp time = SearchCurrent[0]->time; speed = 0; for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ speed += SearchCurrent[ThreadId]->speed; } cpu = SearchCurrent[0]->cpu; node_nb = 0; for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ node_nb += SearchCurrent[ThreadId]->node_nb; } send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload %.0f",time*1000.0,node_nb,speed,cpu*1000.0); trans_stats(Trans); // pawn_stats(); // material_stats(); // best move bestThreadId = 0; for (ThreadId = 1; ThreadId < NumberThreads; ThreadId++){ if (SearchBest[bestThreadId][0].depth < SearchBest[ThreadId][0].depth || (SearchBest[bestThreadId][0].depth == SearchBest[ThreadId][0].depth && SearchBest[bestThreadId][0].value < SearchBest[ThreadId][0].value)){ bestThreadId = ThreadId; } } move = SearchBest[bestThreadId][0].move; pv = SearchBest[bestThreadId][0].pv; move_to_string(move,move_string,256); /* move_to_string(SearchBest[1][0].move,ponder_string,256); if (SearchBest[0][0].move != SearchBest[1][0].move){ FILE *fp; fp=fopen("toga.log","a+"); fprintf(fp,"move: %s depth: %d value: %d move: %s depth: %d value: %d\n",move_string,SearchBest[0][0].depth, SearchBest[0][0].value, ponder_string,SearchBest[1][0].depth, SearchBest[1][0].value); fclose(fp); }*/ if (pv[0] == move && move_is_ok(pv[1])) { move_to_string(pv[1],ponder_string,256); send("bestmove %s ponder %s",move_string,ponder_string); } else { send("bestmove %s",move_string); } } // get() void get(char string[], int size) { ASSERT(string!=NULL); ASSERT(size>=65536); if (!my_file_read_line(stdin,string,size)) { // EOF exit(EXIT_SUCCESS); } } // send() void send(const char format[], ...) { va_list arg_list; char string[4096]; ASSERT(format!=NULL); va_start(arg_list,format); vsprintf(string,format,arg_list); va_end(arg_list); fprintf(stdout,"%s\n",string); } // string_equal() static bool string_equal(const char s1[], const char s2[]) { ASSERT(s1!=NULL); ASSERT(s2!=NULL); return strcmp(s1,s2) == 0; } // string_start_with() static bool string_start_with(const char s1[], const char s2[]) { ASSERT(s1!=NULL); ASSERT(s2!=NULL); return strstr(s1,s2) == s1; } // end of protocol.cpp toga2-3.0.0.1SE1/src/search_full.h0000644000175000017500000000066412074225216016016 0ustar oliveroliver // search_full.h #ifndef SEARCH_FULL_H #define SEARCH_FULL_H // includes #include "board.h" #include "util.h" // functions extern void search_full_init (list_t * list, board_t * board, int ThreadId); extern int search_full_root (list_t * list, board_t * board, int a, int b, int depth, int search_type, int ThreadId); extern bool egbb_is_loaded; #endif // !defined SEARCH_FULL_H // end of search_full.h toga2-3.0.0.1SE1/src/copying.txt0000644000175000017500000004365511125217320015567 0ustar oliveroliver GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. toga2-3.0.0.1SE1/src/pv.h0000644000175000017500000000074011125217320014140 0ustar oliveroliver // pv.h #ifndef PV_H #define PV_H // includes #include "board.h" #include "move.h" #include "util.h" // macros #define PV_CLEAR(pv) (*(pv)=MoveNone) // functions extern bool pv_is_ok (const mv_t pv[]); extern void pv_copy (mv_t dst[], const mv_t src[]); extern void pv_cat (mv_t dst[], const mv_t src[], int move); extern bool pv_to_string (const mv_t pv[], char string[], int size); #endif // !defined PV_H // end of pv.h toga2-3.0.0.1SE1/src/move_gen.cpp0000644000175000017500000004667111125217324015666 0ustar oliveroliver // move_gen.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "list.h" #include "move.h" #include "move_evasion.h" #include "move_gen.h" #include "move_legal.h" #include "piece.h" #include "util.h" // prototypes static void add_moves (list_t * list, const board_t * board); static void add_captures (list_t * list, const board_t * board); static void add_quiet_moves (list_t * list, const board_t * board); static void add_promotes (list_t * list, const board_t * board); static void add_en_passant_captures (list_t * list, const board_t * board); static void add_castle_moves (list_t * list, const board_t * board); // functions // gen_legal_moves() void gen_legal_moves(list_t * list, board_t * board) { attack_t attack[1]; ASSERT(list!=NULL); ASSERT(board!=NULL); attack_set(attack,board); if (ATTACK_IN_CHECK(attack)) { gen_legal_evasions(list,board,attack); } else { gen_moves(list,board); list_filter(list,board,&pseudo_is_legal,true); } // debug ASSERT(list_is_ok(list)); } // gen_moves() void gen_moves(list_t * list, const board_t * board) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); LIST_CLEAR(list); add_moves(list,board); add_en_passant_captures(list,board); add_castle_moves(list,board); // debug ASSERT(list_is_ok(list)); } // gen_captures() void gen_captures(list_t * list, const board_t * board) { ASSERT(list!=NULL); ASSERT(board!=NULL); LIST_CLEAR(list); add_captures(list,board); add_en_passant_captures(list,board); // debug ASSERT(list_is_ok(list)); } // gen_quiet_moves() void gen_quiet_moves(list_t * list, const board_t * board) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); LIST_CLEAR(list); add_quiet_moves(list,board); add_castle_moves(list,board); // debug ASSERT(list_is_ok(list)); } // add_moves() static void add_moves(list_t * list, const board_t * board) { int me, opp; int opp_flag; const sq_t * ptr; int from, to; int piece, capture; const inc_t * inc_ptr; int inc; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); // piece moves for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; inc_ptr = PIECE_INC(piece); if (PIECE_IS_SLIDER(piece)) { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) { LIST_ADD(list,MOVE_MAKE(from,to)); } if (FLAG_IS(capture,opp_flag)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } else { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; capture = board->square[to]; if (capture == Empty || FLAG_IS(capture,opp_flag)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } // pawn moves inc = PAWN_MOVE_INC(me); for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { to = from + (inc-1); if (FLAG_IS(board->square[to],opp_flag)) { add_pawn_move(list,from,to); } to = from + (inc+1); if (FLAG_IS(board->square[to],opp_flag)) { add_pawn_move(list,from,to); } to = from + inc; if (board->square[to] == Empty) { add_pawn_move(list,from,to); if (PAWN_RANK(from,me) == Rank2) { to = from + (2*inc); if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } // add_captures() static void add_captures(list_t * list, const board_t * board) { int me, opp; int opp_flag; const sq_t * ptr; int from, to; int piece, capture; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); // piece captures for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; switch (PIECE_TYPE(piece)) { case Knight64: to = from - 33; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 31; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 18; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 14; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 14; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 18; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 31; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 33; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Bishop64: for (to = from-17; (capture=board->square[to]) == Empty; to -= 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-15; (capture=board->square[to]) == Empty; to -= 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+15; (capture=board->square[to]) == Empty; to += 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+17; (capture=board->square[to]) == Empty; to += 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Rook64: for (to = from-16; (capture=board->square[to]) == Empty; to -= 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-1; (capture=board->square[to]) == Empty; to -= 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+1; (capture=board->square[to]) == Empty; to += 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+16; (capture=board->square[to]) == Empty; to += 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Queen64: for (to = from-17; (capture=board->square[to]) == Empty; to -= 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-16; (capture=board->square[to]) == Empty; to -= 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-15; (capture=board->square[to]) == Empty; to -= 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-1; (capture=board->square[to]) == Empty; to -= 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+1; (capture=board->square[to]) == Empty; to += 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+15; (capture=board->square[to]) == Empty; to += 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+16; (capture=board->square[to]) == Empty; to += 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+17; (capture=board->square[to]) == Empty; to += 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case King64: to = from - 17; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 16; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 15; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 1; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 1; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 15; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 16; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 17; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; default: ASSERT(false); break; } } // pawn captures if (COLOUR_IS_WHITE(me)) { for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { to = from + 15; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); to = from + 17; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); // promote if (SQUARE_RANK(from) == Rank7) { to = from + 16; if (board->square[to] == Empty) { add_promote(list,MOVE_MAKE(from,to)); } } } } else { // black for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { to = from - 17; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); to = from - 15; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); // promote if (SQUARE_RANK(from) == Rank2) { to = from - 16; if (board->square[to] == Empty) { add_promote(list,MOVE_MAKE(from,to)); } } } } } // add_quiet_moves() static void add_quiet_moves(list_t * list, const board_t * board) { int me; const sq_t * ptr; int from, to; int piece; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; // piece moves for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; switch (PIECE_TYPE(piece)) { case Knight64: to = from - 33; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 31; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 18; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 14; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 14; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 18; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 31; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 33; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Bishop64: for (to = from-17; board->square[to] == Empty; to -= 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-15; board->square[to] == Empty; to -= 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+15; board->square[to] == Empty; to += 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+17; board->square[to] == Empty; to += 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } break; case Rook64: for (to = from-16; board->square[to] == Empty; to -= 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-1; board->square[to] == Empty; to -= 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+1; board->square[to] == Empty; to += 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+16; board->square[to] == Empty; to += 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } break; case Queen64: for (to = from-17; board->square[to] == Empty; to -= 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-16; board->square[to] == Empty; to -= 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-15; board->square[to] == Empty; to -= 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-1; board->square[to] == Empty; to -= 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+1; board->square[to] == Empty; to += 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+15; board->square[to] == Empty; to += 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+16; board->square[to] == Empty; to += 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+17; board->square[to] == Empty; to += 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } break; case King64: to = from - 17; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 16; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 15; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 1; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 1; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 15; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 16; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 17; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); break; default: ASSERT(false); break; } } // pawn moves if (COLOUR_IS_WHITE(me)) { for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { // non promotes if (SQUARE_RANK(from) != Rank7) { to = from + 16; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); if (SQUARE_RANK(from) == Rank2) { to = from + 32; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } } else { // black for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { // non promotes if (SQUARE_RANK(from) != Rank2) { to = from - 16; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); if (SQUARE_RANK(from) == Rank7) { to = from - 32; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } } } // add_promotes() static void add_promotes(list_t * list, const board_t * board) { int me; int inc; const sq_t * ptr; int from, to; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; inc = PAWN_MOVE_INC(me); for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { if (PAWN_RANK(from,me) == Rank7) { to = from + inc; if (board->square[to] == Empty) { add_promote(list,MOVE_MAKE(from,to)); } } } } // add_en_passant_captures() static void add_en_passant_captures(list_t * list, const board_t * board) { int from, to; int me; int inc; int pawn; ASSERT(list!=NULL); ASSERT(board!=NULL); to = board->ep_square; if (to != SquareNone) { me = board->turn; inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); from = to - (inc-1); if (board->square[from] == pawn) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } from = to - (inc+1); if (board->square[from] == pawn) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } } } // add_castle_moves() static void add_castle_moves(list_t * list, const board_t * board) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); if (COLOUR_IS_WHITE(board->turn)) { if ((board->flags & FlagsWhiteKingCastle) != 0 && board->square[F1] == Empty && board->square[G1] == Empty && !is_attacked(board,F1,Black)) { LIST_ADD(list,MOVE_MAKE_FLAGS(E1,G1,MoveCastle)); } if ((board->flags & FlagsWhiteQueenCastle) != 0 && board->square[D1] == Empty && board->square[C1] == Empty && board->square[B1] == Empty && !is_attacked(board,D1,Black)) { LIST_ADD(list,MOVE_MAKE_FLAGS(E1,C1,MoveCastle)); } } else { // black if ((board->flags & FlagsBlackKingCastle) != 0 && board->square[F8] == Empty && board->square[G8] == Empty && !is_attacked(board,F8,White)) { LIST_ADD(list,MOVE_MAKE_FLAGS(E8,G8,MoveCastle)); } if ((board->flags & FlagsBlackQueenCastle) != 0 && board->square[D8] == Empty && board->square[C8] == Empty && board->square[B8] == Empty && !is_attacked(board,D8,White)) { LIST_ADD(list,MOVE_MAKE_FLAGS(E8,C8,MoveCastle)); } } } // add_pawn_move() void add_pawn_move(list_t * list, int from, int to) { int move; ASSERT(list!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); move = MOVE_MAKE(from,to); if (SQUARE_IS_PROMOTE(to)) { LIST_ADD(list,move|MovePromoteQueen); LIST_ADD(list,move|MovePromoteKnight); LIST_ADD(list,move|MovePromoteRook); LIST_ADD(list,move|MovePromoteBishop); } else { LIST_ADD(list,move); } } // add_promote() void add_promote(list_t * list, int move) { ASSERT(list!=NULL); ASSERT(move_is_ok(move)); ASSERT((move&~07777)==0); // HACK ASSERT(SQUARE_IS_PROMOTE(MOVE_TO(move))); LIST_ADD(list,move|MovePromoteQueen); LIST_ADD(list,move|MovePromoteKnight); LIST_ADD(list,move|MovePromoteRook); LIST_ADD(list,move|MovePromoteBishop); } // end of move_gen.cpp toga2-3.0.0.1SE1/src/search.cpp0000644000175000017500000006047612120151332015323 0ustar oliveroliver // search.cpp // includes #ifdef _WIN32 #include #include #else #include #include #include #endif #include #include #include "attack.h" #include "board.h" #include "book.h" #include "colour.h" #include "list.h" #include "material.h" #include "move.h" #include "move_do.h" #include "move_gen.h" #include "option.h" #include "pawn.h" #include "protocol.h" #include "pv.h" #include "search.h" #include "search_full.h" #include "sort.h" #include "trans.h" #include "util.h" #include "value.h" // constants static const bool UseCpuTime = false; // false static const bool UseEvent = true; // true static const bool UseShortSearch = true; static const int ShortSearchDepth = 1; static const bool DispBest = true; // true static const bool DispDepthStart = true; // true static const bool DispDepthEnd = true; // true static const bool DispRoot = true; // true static const bool DispStat = true; // true static const bool UseEasy = true; // singular move static const int EasyThreshold = 150; static const double EasyRatio = 0.20; static const bool UseEarly = true; // early iteration end static const double EarlyRatio = 0.60; static const bool UseBad = true; static const int BadThreshold = 50; // 50 static const bool UseExtension = true; // variables static search_multipv_t save_multipv[MultiPVMax]; #ifdef _WIN32 static HANDLE threat_handle[MaxThreads]; #else static pthread_t threat_handle[MaxThreads]; static my_sem_t thread_runnable[MaxThreads]; #endif int NumberThreads = 1; //bool trans_endgame; //CRITICAL_SECTION CriticalSection; search_input_t SearchInput[1]; search_info_t SearchInfo[MaxThreads][1]; search_root_t SearchRoot[MaxThreads][1]; search_current_t SearchCurrent[MaxThreads][1]; search_best_t SearchBest[MaxThreads][MultiPVMax]; // prototypes static void search_send_stat (int ThreadId); #ifdef _WIN32 unsigned __stdcall search_thread (void *param); #else void * search_thread (void *param); #endif // functions // depth_is_ok() bool depth_is_ok(int depth) { return depth > -128 && depth < DepthMax; } // height_is_ok() bool height_is_ok(int height) { return height >= 0 && height < HeightMax; } // search_clear() void search_clear() { int ThreadId; // SearchInput SearchInput->infinite = false; SearchInput->depth_is_limited = false; SearchInput->depth_limit = 0; SearchInput->time_is_limited = false; SearchInput->time_limit_1 = 0.0; SearchInput->time_limit_2 = 0.0; // SearchInfo for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ SearchInfo[ThreadId]->can_stop = false; SearchInfo[ThreadId]->stop = false; SearchInfo[ThreadId]->stopped = false; SearchInfo[ThreadId]->exited = false; SearchInfo[ThreadId]->check_nb = 10000; // was 100000 SearchInfo[ThreadId]->check_inc = 10000; // was 100000 SearchInfo[ThreadId]->last_time = 0.0; // SearchBest SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].move = MoveNone; SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].value = 0; SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].flags = SearchUnknown; SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].depth = 0; PV_CLEAR(SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].pv); // SearchRoot SearchRoot[ThreadId]->depth = 0; SearchRoot[ThreadId]->move = MoveNone; SearchRoot[ThreadId]->move_pos = 0; SearchRoot[ThreadId]->move_nb = 0; SearchRoot[ThreadId]->last_value = 0; SearchRoot[ThreadId]->bad_1 = false; SearchRoot[ThreadId]->bad_2 = false; SearchRoot[ThreadId]->change = false; SearchRoot[ThreadId]->easy = false; SearchRoot[ThreadId]->flag = false; // SearchCurrent SearchCurrent[ThreadId]->max_depth = 0; SearchCurrent[ThreadId]->node_nb = 0; SearchCurrent[ThreadId]->time = 0.0; SearchCurrent[ThreadId]->speed = 0.0; SearchCurrent[ThreadId]->cpu = 0.0; } } #ifdef _WIN32 void start_suspend_threads(){ static int ThreadIds[MaxThreads]; static unsigned internalThreadIds[MaxThreads]; int i; // start and suspend threads for (i = 1; i < NumberThreads; i++){ ThreadIds[i-1] = i; threat_handle[i-1] = (HANDLE) _beginthreadex( NULL, 0, &search_thread, &ThreadIds[i-1], CREATE_SUSPENDED, &internalThreadIds[i-1]); } } void resume_threads(){ int i; // resume threads for (i = 1; i < NumberThreads; i++){ ResumeThread(threat_handle[i-1]); } } #else void start_suspend_threads(){ static int ThreadIds[MaxThreads]; int i; // start and suspend threads for (i = 1; i < NumberThreads; i++){ ThreadIds[i-1] = i; my_sem_init(&(thread_runnable[i-1]),0); pthread_create(&(threat_handle[i-1]),NULL, search_thread,&(ThreadIds[i-1])); } } void resume_threads(){ int i; // resume threads for (i = 1; i < NumberThreads; i++){ my_sem_post(&(thread_runnable[i-1])); } } #endif // exit_threads() void exit_threads() { int ThreadId; bool all_exited=false; SearchInput->exit_engine=true; // hack resume_threads(); while (!all_exited){ all_exited = true; for (ThreadId = 1; ThreadId < NumberThreads; ThreadId++){ if (!SearchInfo[ThreadId]->exited) all_exited = false; } } SearchInput->exit_engine=false; // hack } // search() void search() { int move; int i; bool all_stopped; int ThreadId; for (i = 0; i < MultiPVMax; i++){ save_multipv[i].mate = 0; save_multipv[i].depth = 0; save_multipv[i].max_depth = 0; save_multipv[i].value = 0; save_multipv[i].time = 0; save_multipv[i].node_nb = 0; strcpy(save_multipv[i].pv_string,""); } SearchInput->multipv = option_get_int("MultiPV")-1; for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ SearchCurrent[ThreadId]->multipv = 0; } ASSERT(board_is_ok(SearchInput->board)); // opening book if (option_get_bool("OwnBook") && !SearchInput->infinite) { move = book_move(SearchInput->board); if (move != MoveNone) { // play book move SearchBest[0][SearchCurrent[ThreadId]->multipv].move = move; SearchBest[0][SearchCurrent[ThreadId]->multipv].value = 1; SearchBest[0][SearchCurrent[ThreadId]->multipv].flags = SearchExact; SearchBest[0][SearchCurrent[ThreadId]->multipv].depth = 1; SearchBest[0][SearchCurrent[ThreadId]->multipv].pv[0] = move; SearchBest[0][SearchCurrent[ThreadId]->multipv].pv[1] = MoveNone; search_update_best(0); return; } } // SearchInput gen_legal_moves(SearchInput->list,SearchInput->board); if (LIST_SIZE(SearchInput->list) < SearchInput->multipv+1){ SearchInput->multipv = LIST_SIZE(SearchInput->list)-1; } if (LIST_SIZE(SearchInput->list) <= 1) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = 4; // was 1 } trans_inc_date(Trans); // resume threads resume_threads(); //SearchInfo_smp->stop = true; search_smp(0); for (ThreadId = 1; ThreadId < NumberThreads; ThreadId++){ // stop threads SearchInfo[ThreadId]->stop = true; } all_stopped = false; while (!all_stopped){ all_stopped = true; for (ThreadId = 1; ThreadId < NumberThreads; ThreadId++){ if (!SearchInfo[ThreadId]->stopped) all_stopped = false; } } } #ifdef _WIN32 unsigned __stdcall search_thread (void *param) { int ThreadId = *((int*)param); SearchInfo[ThreadId]->exited= false; while (!SearchInput->exit_engine){ search_smp(ThreadId); SearchInfo[ThreadId]->stopped = true; SuspendThread(threat_handle[ThreadId-1]); } SearchInfo[ThreadId]->exited= true; _endthreadex( 0 ); return 0; } #else void * search_thread (void *param) { int ThreadId = *((int*)param); SearchInfo[ThreadId]->exited= false; my_sem_wait(&(thread_runnable[ThreadId-1])); while (!SearchInput->exit_engine){ search_smp(ThreadId); SearchInfo[ThreadId]->stopped = true; my_sem_wait(&(thread_runnable[ThreadId-1])); } SearchInfo[ThreadId]->exited= true; return NULL; } #endif // search_smp() void search_smp(int ThreadId) { int depth; int i; int delta, a, b; bool search_ready; sint64 node_nb; double speed; // SearchInfo if (setjmp(SearchInfo[ThreadId]->buf) != 0) { ASSERT(SearchInfo[ThreadId]->can_stop); ASSERT(SearchBest[ThreadId]->move!=MoveNone); search_update_current(ThreadId); return; } // SearchRoot list_copy(SearchRoot[ThreadId]->list,SearchInput->list); // SearchCurrent board_copy(SearchCurrent[ThreadId]->board,SearchInput->board); my_timer_reset(SearchCurrent[ThreadId]->timer); my_timer_start(SearchCurrent[ThreadId]->timer); // init sort_init(ThreadId); search_full_init(SearchRoot[ThreadId]->list,SearchCurrent[ThreadId]->board,ThreadId); // analyze game for evaluation /*if (SearchCurrent[ThreadId]->board->piece_size[White] < 3 && SearchCurrent[ThreadId]->board->piece_size[Black] < 3 && (SearchCurrent[ThreadId]->board->pawn_size[White]+SearchCurrent[ThreadId]->board->pawn_size[Black]) > 0){ trans_endgame = true; } else{ trans_endgame = false; } */ // iterative deepening search_ready = false; delta = 16; if (ThreadId == 0){ // main thread for (depth = 1; depth < DepthMax; depth++) { for (SearchCurrent[ThreadId]->multipv = 0; SearchCurrent[ThreadId]->multipv <= SearchInput->multipv; SearchCurrent[ThreadId]->multipv++){ if (DispDepthStart && SearchCurrent[ThreadId]->multipv == 0) send("info depth %d",depth); SearchCurrent[ThreadId]->act_iteration = depth; SearchRoot[ThreadId]->bad_1 = false; SearchRoot[ThreadId]->change = false; board_copy(SearchCurrent[ThreadId]->board,SearchInput->board); // Aspiration windows (JD) if (depth <= 4){ // TODO: Try other values a = -ValueInf; b = +ValueInf; } while (1){ if (UseShortSearch && depth <= ShortSearchDepth) { search_full_root(SearchRoot[ThreadId]->list,SearchCurrent[ThreadId]->board,a,b,depth,SearchShort,ThreadId); } else { search_full_root(SearchRoot[ThreadId]->list,SearchCurrent[ThreadId]->board,a,b,depth,SearchNormal,ThreadId); } // Aspiration windows // break on mate value if (value_is_mate(SearchBest[ThreadId]->value)) break; // adjust on fail high/low if (SearchBest[ThreadId]->value <= a){ a -= delta; delta += delta; } else if (SearchBest[ThreadId]->value >= b){ b += delta; delta += delta; } else { a = SearchBest[ThreadId]->value-delta; b = SearchBest[ThreadId]->value+delta; break; } } search_update_current(ThreadId); node_nb = 0; speed = 0; // calculate nodes/speed for (i = 0; i < NumberThreads; i++){ node_nb += SearchCurrent[i]->node_nb; speed += SearchCurrent[i]->speed; } if (DispDepthEnd && SearchCurrent[ThreadId]->multipv == SearchInput->multipv) { send("info depth %d seldepth %d time %.0f nodes " S64_FORMAT " nps %.0f",depth,SearchCurrent[ThreadId]->max_depth,SearchCurrent[ThreadId]->time*1000.0,node_nb,speed); } // update search info if (depth >= 1) SearchInfo[ThreadId]->can_stop = true; if (depth == 1 && LIST_SIZE(SearchRoot[ThreadId]->list) >= 2 && LIST_VALUE(SearchRoot[ThreadId]->list,0) >= LIST_VALUE(SearchRoot[ThreadId]->list,1) + EasyThreshold) { SearchRoot[ThreadId]->easy = true; } if (UseBad && depth > 1) { SearchRoot[ThreadId]->bad_2 = SearchRoot[ThreadId]->bad_1; SearchRoot[ThreadId]->bad_1 = false; ASSERT(SearchRoot[ThreadId]->bad_2==(SearchBest[ThreadId]->value<=SearchRoot[ThreadId]->last_value-BadThreshold)); } SearchRoot[ThreadId]->last_value = SearchBest[ThreadId][0].value; // stop search? if (SearchInput->depth_is_limited && SearchCurrent[ThreadId]->multipv >= SearchInput->multipv && depth >= SearchInput->depth_limit) { SearchRoot[ThreadId]->flag = true; } if (SearchInput->time_is_limited && SearchCurrent[ThreadId]->time >= SearchInput->time_limit_1 && !SearchRoot[ThreadId]->bad_2) { SearchRoot[ThreadId]->flag = true; } if (UseEasy && SearchInput->time_is_limited && SearchCurrent[ThreadId]->time >= SearchInput->time_limit_1 * EasyRatio && SearchRoot[ThreadId]->easy) { ASSERT(!SearchRoot[ThreadId]->bad_2); ASSERT(!SearchRoot[ThreadId]->change); SearchRoot[ThreadId]->flag = true; } if (UseEarly && SearchInput->time_is_limited && SearchCurrent[ThreadId]->time >= SearchInput->time_limit_1 * EarlyRatio && !SearchRoot[ThreadId]->bad_2 && !SearchRoot[ThreadId]->change) { SearchRoot[ThreadId]->flag = true; } if (SearchInfo[ThreadId]->can_stop && (SearchInfo[ThreadId]->stop || (SearchRoot[ThreadId]->flag && !SearchInput->infinite))) { search_ready = true; break; } } if (search_ready) break; } } else { for (depth = 1; depth < DepthMax; depth++) { SearchCurrent[ThreadId]->act_iteration = depth; SearchInfo[ThreadId]->can_stop = true; board_copy(SearchCurrent[ThreadId]->board,SearchInput->board); // Aspiration windows if (depth <= 4){ // Try other values a = -ValueInf; b = +ValueInf; } while (1){ if (UseShortSearch && depth <= ShortSearchDepth) { search_full_root(SearchRoot[ThreadId]->list,SearchCurrent[ThreadId]->board,a,b,depth,SearchShort,ThreadId); } else { search_full_root(SearchRoot[ThreadId]->list,SearchCurrent[ThreadId]->board,a,b,depth,SearchNormal,ThreadId); } if (value_is_mate(SearchBest[ThreadId]->value)) break; if (SearchBest[ThreadId]->value <= a){ a -= delta; delta += delta; } else if (SearchBest[ThreadId]->value >= b){ b += delta; delta += delta; } else { a = SearchBest[ThreadId]->value-delta; b = SearchBest[ThreadId]->value+delta; break; } } search_update_current(ThreadId); } } } // search_update_best() void search_update_best(int ThreadId) { int move, value, flags, depth, max_depth; const mv_t * pv; double time; sint64 node_nb; int mate, i, z; bool found; char move_string[256], pv_string[512]; search_update_current(ThreadId); #ifdef _WIN32 EnterCriticalSection(&CriticalSection); #else pthread_mutex_lock(&CriticalSection); #endif /* if (DispBest && (save_multipv[0].depth < SearchBest[ThreadId][0].depth || (save_multipv[0].depth == SearchBest[ThreadId][0].depth && save_multipv[0].value < SearchBest[ThreadId][0].value))) {*/ if (ThreadId == 0) { // Norman Schmidt (kranium): multi-pv fix move = SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].move; value = SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].value; flags = SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].flags; depth = SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].depth; pv = SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].pv; max_depth = SearchCurrent[ThreadId]->max_depth; time = SearchCurrent[ThreadId]->time; node_nb = SearchCurrent[ThreadId]->node_nb; move_to_string(move,move_string,256); pv_to_string(pv,pv_string,512); mate = value_to_mate(value); if (SearchCurrent[ThreadId]->multipv == 0){ save_multipv[SearchCurrent[ThreadId]->multipv].mate = mate; save_multipv[SearchCurrent[ThreadId]->multipv].depth = depth; save_multipv[SearchCurrent[ThreadId]->multipv].max_depth = max_depth; save_multipv[SearchCurrent[ThreadId]->multipv].value = value; save_multipv[SearchCurrent[ThreadId]->multipv].time = time*1000.0; save_multipv[SearchCurrent[ThreadId]->multipv].node_nb = node_nb; strcpy(save_multipv[SearchCurrent[ThreadId]->multipv].pv_string,pv_string); } else{ found = false; for (i = 0; i < SearchCurrent[ThreadId]->multipv; i++){ if (save_multipv[i].value < value){ found = true; break; } } if (found){ for (z = SearchCurrent[ThreadId]->multipv; z > i; z--){ save_multipv[z].mate = save_multipv[z-1].mate; save_multipv[z].depth = save_multipv[z-1].depth; save_multipv[z].max_depth = save_multipv[z-1].max_depth; save_multipv[z].value = save_multipv[z-1].value; save_multipv[z].time = save_multipv[z-1].time; save_multipv[z].node_nb = save_multipv[z-1].node_nb; strcpy(save_multipv[z].pv_string,save_multipv[z-1].pv_string); } save_multipv[i].mate = mate; save_multipv[i].depth = depth; save_multipv[i].max_depth = max_depth; save_multipv[i].value = value; save_multipv[i].time = time*1000.0; save_multipv[i].node_nb = node_nb; strcpy(save_multipv[i].pv_string,pv_string); } else{ save_multipv[SearchCurrent[ThreadId]->multipv].mate = mate; save_multipv[SearchCurrent[ThreadId]->multipv].depth = depth; save_multipv[SearchCurrent[ThreadId]->multipv].max_depth = max_depth; save_multipv[SearchCurrent[ThreadId]->multipv].value = value; save_multipv[SearchCurrent[ThreadId]->multipv].time = time*1000.0; save_multipv[SearchCurrent[ThreadId]->multipv].node_nb = node_nb; strcpy(save_multipv[SearchCurrent[ThreadId]->multipv].pv_string,pv_string); } } if (depth > 1 || (depth == 1 && SearchCurrent[ThreadId]->multipv == SearchInput->multipv)){ for (i = 0; i <= SearchInput->multipv; i++){ if (save_multipv[i].mate == 0) { // normal evaluation if (false) { } else if (flags == SearchExact) { send("info multipv %d depth %d seldepth %d score cp %d time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].value,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchLower) { send("info multipv %d depth %d seldepth %d score cp %d lowerbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].value,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchUpper) { send("info multipv %d depth %d seldepth %d score cp %d upperbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].value,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } } else { // mate announcement if (false) { } else if (flags == SearchExact) { send("info multipv %d depth %d seldepth %d score mate %d time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].mate,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchLower) { send("info multipv %d depth %d seldepth %d score mate %d lowerbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].mate,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } else if (flags == SearchUpper) { send("info multipv %d depth %d seldepth %d score mate %d upperbound time %.0f nodes " S64_FORMAT " pv %s",i+1,save_multipv[i].depth,save_multipv[i].max_depth,save_multipv[i].mate,save_multipv[i].time,save_multipv[i].node_nb,save_multipv[i].pv_string); } } } } } // update time-management info /* danger = false; for (i = 1; i < NumberThreads; i++){ if (SearchBest[0][0].depth < SearchBest[i][0].depth || (SearchBest[0][0].depth == SearchBest[i][0].depth && SearchBest[0][0].value < SearchBest[i][0].value)){ danger = true; } }*/ if (UseBad && ThreadId == 0 && SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].depth > 1) { if (SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].value <= SearchRoot[ThreadId]->last_value - BadThreshold) { SearchRoot[ThreadId]->bad_1 = true; SearchRoot[ThreadId]->easy = false; SearchRoot[ThreadId]->flag = false; } else { SearchRoot[ThreadId]->bad_1 = false; } } #ifdef _WIN32 LeaveCriticalSection(&CriticalSection); #else pthread_mutex_unlock(&CriticalSection); #endif } // search_update_root() void search_update_root(int ThreadId) { int move, move_pos, move_nb; double time; sint64 node_nb; char move_string[256]; if (DispRoot && ThreadId == 0) { search_update_current(ThreadId); if (SearchCurrent[ThreadId]->time >= 1.0) { move = SearchRoot[ThreadId]->move; move_pos = SearchRoot[ThreadId]->move_pos; move_nb = SearchRoot[ThreadId]->move_nb; time = SearchCurrent[ThreadId]->time; node_nb = SearchCurrent[ThreadId]->node_nb; move_to_string(move,move_string,256); send("info currmove %s currmovenumber %d",move_string,move_pos+1); } } } // search_update_current() void search_update_current(int ThreadId) { my_timer_t *timer; sint64 node_nb; double time, speed, cpu; timer = SearchCurrent[ThreadId]->timer; node_nb = SearchCurrent[ThreadId]->node_nb; time = (UseCpuTime) ? my_timer_elapsed_cpu(timer) : my_timer_elapsed_real(timer); speed = (time >= 1.0) ? double(node_nb) / time : 0.0; cpu = my_timer_cpu_usage(timer); SearchCurrent[ThreadId]->time = time; SearchCurrent[ThreadId]->speed = speed; SearchCurrent[ThreadId]->cpu = cpu; } // search_check() void search_check(int ThreadId) { if (ThreadId == 0){ search_send_stat(ThreadId); if (UseEvent) event(); if (SearchInput->depth_is_limited && SearchRoot[ThreadId]->depth > SearchInput->depth_limit) { SearchRoot[ThreadId]->flag = true; } if (SearchInput->time_is_limited && SearchCurrent[ThreadId]->time >= SearchInput->time_limit_2) { SearchRoot[ThreadId]->flag = true; } if (SearchInput->time_is_limited && SearchCurrent[ThreadId]->time >= SearchInput->time_limit_1 && !SearchRoot[ThreadId]->bad_1 && !SearchRoot[ThreadId]->bad_2 && (!UseExtension || SearchRoot[ThreadId]->move_pos == 0)) { SearchRoot[ThreadId]->flag = true; } if (SearchInfo[ThreadId]->can_stop && (SearchInfo[ThreadId]->stop || (SearchRoot[ThreadId]->flag && !SearchInput->infinite))) { longjmp(SearchInfo[ThreadId]->buf,1); } } else{ if (SearchInfo[ThreadId]->stop){ longjmp(SearchInfo[ThreadId]->buf,1); } } } // search_send_stat() static void search_send_stat(int ThreadId) { double time, speed, cpu; sint64 node_nb; int i; search_update_current(ThreadId); if (DispStat && ThreadId == 0 && SearchCurrent[ThreadId]->time >= SearchInfo[ThreadId]->last_time + 1.0) { // at least one-second gap SearchInfo[ThreadId]->last_time = SearchCurrent[ThreadId]->time; time = SearchCurrent[ThreadId]->time; speed = SearchCurrent[ThreadId]->speed; cpu = SearchCurrent[ThreadId]->cpu; node_nb = 0; speed = 0; for (i = 0; i < NumberThreads; i++){ node_nb += SearchCurrent[ThreadId]->node_nb; speed += SearchCurrent[ThreadId]->speed; } send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload %.0f",time*1000.0,node_nb,speed,cpu*1000.0); trans_stats(Trans); } } // end of search.cpp toga2-3.0.0.1SE1/src/piece.cpp0000644000175000017500000000526611125217316015150 0ustar oliveroliver // piece.cpp // includes #include #include "colour.h" #include "piece.h" #include "util.h" // "constants" const int PawnMake[ColourNb] = { WhitePawn256, BlackPawn256 }; const int PieceFrom12[12] = { WhitePawn256, BlackPawn256, WhiteKnight256, BlackKnight256, WhiteBishop256, BlackBishop256, WhiteRook256, BlackRook256, WhiteQueen256, BlackQueen256, WhiteKing256, BlackKing256, }; static const char PieceString[12+1] = "PpNnBbRrQqKk"; const inc_t PawnMoveInc[ColourNb] = { +16, -16, }; const inc_t KnightInc[8+1] = { -33, -31, -18, -14, +14, +18, +31, +33, 0 }; const inc_t BishopInc[4+1] = { -17, -15, +15, +17, 0 }; const inc_t RookInc[4+1] = { -16, -1, +1, +16, 0 }; const inc_t QueenInc[8+1] = { -17, -16, -15, -1, +1, +15, +16, +17, 0 }; const inc_t KingInc[8+1] = { -17, -16, -15, -1, +1, +15, +16, +17, 0 }; // variables int PieceTo12[PieceNb]; int PieceOrder[PieceNb]; const inc_t * PieceInc[PieceNb]; // functions // piece_init() void piece_init() { int piece, piece_12; // PieceTo12[] for (piece = 0; piece < PieceNb; piece++) PieceTo12[piece] = -1; for (piece_12 = 0; piece_12 < 12; piece_12++) { PieceTo12[PieceFrom12[piece_12]] = piece_12; } // PieceOrder[] for (piece = 0; piece < PieceNb; piece++) PieceOrder[piece] = -1; for (piece_12 = 0; piece_12 < 12; piece_12++) { PieceOrder[PieceFrom12[piece_12]] = piece_12 >> 1; } // PieceInc[] for (piece = 0; piece < PieceNb; piece++) { PieceInc[piece] = NULL; } PieceInc[WhiteKnight256] = KnightInc; PieceInc[WhiteBishop256] = BishopInc; PieceInc[WhiteRook256] = RookInc; PieceInc[WhiteQueen256] = QueenInc; PieceInc[WhiteKing256] = KingInc; PieceInc[BlackKnight256] = KnightInc; PieceInc[BlackBishop256] = BishopInc; PieceInc[BlackRook256] = RookInc; PieceInc[BlackQueen256] = QueenInc; PieceInc[BlackKing256] = KingInc; } // piece_is_ok() bool piece_is_ok(int piece) { if (piece < 0 || piece >= PieceNb) return false; if (PieceTo12[piece] < 0) return false; return true; } // piece_from_12() int piece_from_12(int piece_12) { ASSERT(piece_12>=0&&piece_12<12); return PieceFrom12[piece_12]; } // piece_to_char() int piece_to_char(int piece) { ASSERT(piece_is_ok(piece)); return PieceString[PIECE_TO_12(piece)]; } // piece_from_char() int piece_from_char(int c) { const char *ptr; ptr = strchr(PieceString,c); if (ptr == NULL) return PieceNone256; return piece_from_12(ptr-PieceString); } // end of piece.cpp toga2-3.0.0.1SE1/src/pv.cpp0000644000175000017500000000256011125217324014501 0ustar oliveroliver // pv.cpp // includes #include #include "board.h" #include "move.h" #include "move_do.h" #include "pv.h" #include "util.h" // functions // pv_is_ok() bool pv_is_ok(const mv_t pv[]) { int pos; int move; if (pv == NULL) return false; for (pos = 0; true; pos++) { if (pos >= 256) return false; move = pv[pos]; if (move == MoveNone) return true; if (!move_is_ok(move)) return false; } return true; } // pv_copy() void pv_copy(mv_t dst[], const mv_t src[]) { ASSERT(pv_is_ok(src)); ASSERT(dst!=NULL); while ((*dst++ = *src++) != MoveNone) ; } // pv_cat() void pv_cat(mv_t dst[], const mv_t src[], int move) { ASSERT(pv_is_ok(src)); ASSERT(dst!=NULL); *dst++ = move; while ((*dst++ = *src++) != MoveNone) ; } // pv_to_string() bool pv_to_string(const mv_t pv[], char string[], int size) { int pos; int move; ASSERT(pv_is_ok(pv)); ASSERT(string!=NULL); ASSERT(size>=512); // init if (size < 512) return false; pos = 0; // loop while ((move = *pv++) != MoveNone) { if (pos != 0) string[pos++] = ' '; move_to_string(move,&string[pos],size-pos); pos += strlen(&string[pos]); } string[pos] = '\0'; return true; } // end of pv.cpp toga2-3.0.0.1SE1/src/book.cpp0000644000175000017500000000774111125217324015014 0ustar oliveroliver // book.cpp // includes #include #include #include #include #include "board.h" #include "book.h" #include "move.h" #include "move_gen.h" #include "util.h" // types struct entry_t { uint64 key; uint16 move; uint16 count; uint16 n; uint16 sum; }; // variables static FILE * BookFile; static int BookSize; // prototypes static int find_pos (uint64 key); static void read_entry (entry_t * entry, int n); static uint64 read_integer (FILE * file, int size); // functions // book_init() void book_init() { BookFile = NULL; BookSize = 0; } // book_open() void book_open(const char file_name[]) { ASSERT(file_name!=NULL); BookFile = fopen(file_name,"rb"); if (BookFile != NULL) { if (fseek(BookFile,0,SEEK_END) == -1) { my_fatal("book_open(): fseek(): %s\n",strerror(errno)); } BookSize = ftell(BookFile) / 16; if (BookSize == -1) my_fatal("book_open(): ftell(): %s\n",strerror(errno)); } } // book_close() void book_close() { if (BookFile != NULL && fclose(BookFile) == EOF) { my_fatal("book_close(): fclose(): %s\n",strerror(errno)); } BookFile = NULL; } // book_move() int book_move(board_t * board) { int best_move; int best_score; int pos; entry_t entry[1]; int move; int score; list_t list[1]; int i; ASSERT(board!=NULL); if (BookFile != NULL && BookSize != 0) { // draw a move according to a fixed probability distribution best_move = MoveNone; best_score = 0; for (pos = find_pos(board->key); pos < BookSize; pos++) { read_entry(entry,pos); if (entry->key != board->key) break; move = entry->move; score = entry->count; // pick this move? ASSERT(score>0); best_score += score; if (my_random(best_score) < score) best_move = move; } if (best_move != MoveNone) { // convert PolyGlot move into Fruit move; TODO: handle promotes gen_legal_moves(list,board); for (i = 0; i < list->size; i++) { move = list->move[i]; if ((move & 07777) == best_move) return move; } } } return MoveNone; } // find_pos() static int find_pos(uint64 key) { int left, right, mid; entry_t entry[1]; // binary search (finds the leftmost entry) left = 0; right = BookSize-1; ASSERT(left<=right); while (left < right) { mid = (left + right) / 2; ASSERT(mid>=left&&midkey) { right = mid; } else { left = mid+1; } } ASSERT(left==right); read_entry(entry,left); return (entry->key == key) ? left : BookSize; } // read_entry() static void read_entry(entry_t * entry, int n) { ASSERT(entry!=NULL); ASSERT(n>=0&&nkey = read_integer(BookFile,8); entry->move = read_integer(BookFile,2); entry->count = read_integer(BookFile,2); entry->n = read_integer(BookFile,2); entry->sum = read_integer(BookFile,2); } // read_integer() static uint64 read_integer(FILE * file, int size) { uint64 n; int i; int b; ASSERT(file!=NULL); ASSERT(size>0&&size<=8); n = 0; for (i = 0; i < size; i++) { b = fgetc(file); if (b == EOF) { if (feof(file)) { my_fatal("read_integer(): fgetc(): EOF reached\n"); } else { // error my_fatal("read_integer(): fgetc(): %s\n",strerror(errno)); } } ASSERT(b>=0&&b<256); n = (n << 8) | b; } return n; } // end of book.cpp toga2-3.0.0.1SE1/src/attack.h0000644000175000017500000000320711125217324014767 0ustar oliveroliver // attack.h #ifndef ATTACK_H #define ATTACK_H // includes #include "board.h" #include "util.h" #include "vector.h" // macros #define IS_IN_CHECK(board,colour) (is_attacked((board),KING_POS((board),(colour)),COLOUR_OPP((colour)))) #define DELTA_INC_LINE(delta) (DeltaIncLine[DeltaOffset+(delta)]) #define DELTA_INC_ALL(delta) (DeltaIncAll[DeltaOffset+(delta)]) #define DELTA_MASK(delta) (DeltaMask[DeltaOffset+(delta)]) #define INC_MASK(inc) (IncMask[IncOffset+(inc)]) #define PIECE_ATTACK(board,piece,from,to) (PSEUDO_ATTACK((piece),(to)-(from))&&line_is_empty((board),(from),(to))) #define PSEUDO_ATTACK(piece,delta) (((piece)&DELTA_MASK(delta))!=0) #define SLIDER_ATTACK(piece,inc) (((piece)&INC_MASK(inc))!=0) #define ATTACK_IN_CHECK(attack) ((attack)->dn!=0) // types struct attack_t { int dn; int ds[2+1]; int di[2+1]; }; // variables extern int DeltaIncLine[DeltaNb]; extern int DeltaIncAll[DeltaNb]; extern int DeltaMask[DeltaNb]; extern int IncMask[IncNb]; // functions extern void attack_init (); extern bool is_attacked (const board_t * board, int to, int colour); extern bool line_is_empty (const board_t * board, int from, int to); extern bool is_pinned (const board_t * board, int square, int colour); extern bool attack_is_ok (const attack_t * attack); extern void attack_set (attack_t * attack, const board_t * board); extern bool piece_attack_king (const board_t * board, int piece, int from, int king); #endif // !defined ATTACK_H // end of attack.h toga2-3.0.0.1SE1/src/colour.h0000644000175000017500000000134111125217322015016 0ustar oliveroliver // colour.h #ifndef COLOUR_H #define COLOUR_H // includes #include "util.h" // constants const int ColourNone = -1; const int White = 0; const int Black = 1; const int ColourNb = 2; const int WhiteFlag = 1 << White; const int BlackFlag = 1 << Black; // macros #define COLOUR_IS_OK(colour) (((colour)&~1)==0) #define COLOUR_IS_WHITE(colour) ((colour)==White) #define COLOUR_IS_BLACK(colour) ((colour)!=White) #define COLOUR_IS(piece,colour) (FLAG_IS((piece),COLOUR_FLAG(colour))) #define FLAG_IS(piece,flag) (((piece)&(flag))!=0) #define COLOUR_OPP(colour) ((colour)^(White^Black)) #define COLOUR_FLAG(colour) ((colour)+1) #endif // !defined COLOUR_H // end of colour.h toga2-3.0.0.1SE1/src/hash.cpp0000644000175000017500000000636311125217314015003 0ustar oliveroliver // hash.cpp // includes #include "board.h" #include "hash.h" #include "piece.h" #include "random.h" #include "square.h" #include "util.h" // variables uint64 Castle64[16]; // prototypes static uint64 hash_counter_key (int piece_12, int count); // functions // hash_init() void hash_init() { int i; for (i = 0; i < 16; i++) Castle64[i] = hash_castle_key(i); } // hash_key() uint64 hash_key(const board_t * board) { uint64 key; int colour; const sq_t * ptr; int sq, piece; ASSERT(board!=NULL); // init key = 0; // pieces for (colour = 0; colour < ColourNb; colour++) { for (ptr = &board->piece[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; key ^= hash_piece_key(piece,sq); } for (ptr = &board->pawn[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; key ^= hash_piece_key(piece,sq); } } // castle flags key ^= hash_castle_key(board->flags); // en-passant square sq = board->ep_square; if (sq != SquareNone) key ^= hash_ep_key(sq); // turn key ^= hash_turn_key(board->turn); return key; } // hash_pawn_key() uint64 hash_pawn_key(const board_t * board) { uint64 key; int colour; const sq_t * ptr; int sq, piece; ASSERT(board!=NULL); // init key = 0; // pawns for (colour = 0; colour < ColourNb; colour++) { for (ptr = &board->pawn[colour][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; key ^= hash_piece_key(piece,sq); } } return key; } // hash_material_key() uint64 hash_material_key(const board_t * board) { uint64 key; int piece_12, count; ASSERT(board!=NULL); // init key = 0; // counters for (piece_12 = 0; piece_12 < 12; piece_12++) { count = board->number[piece_12]; key ^= hash_counter_key(piece_12,count); } return key; } // hash_piece_key() uint64 hash_piece_key(int piece, int square) { ASSERT(piece_is_ok(piece)); ASSERT(SQUARE_IS_OK(square)); return RANDOM_64(RandomPiece+(PIECE_TO_12(piece)^1)*64+SQUARE_TO_64(square)); // HACK: ^1 for PolyGlot book } // hash_castle_key() uint64 hash_castle_key(int flags) { uint64 key; int i; ASSERT((flags&~0xF)==0); key = 0; for (i = 0; i < 4; i++) { if ((flags & (1<=0&&piece_12<12); ASSERT(count>=0&&count<=10); // init key = 0; // counter index = piece_12 * 16; for (i = 0; i < count; i++) key ^= RANDOM_64(index+i); return key; } // end of hash.cpp toga2-3.0.0.1SE1/src/sort.cpp0000644000175000017500000004750211125217314015047 0ustar oliveroliver // sort.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "list.h" #include "move.h" #include "move_check.h" #include "move_evasion.h" #include "move_gen.h" #include "move_legal.h" #include "piece.h" #include "search.h" #include "see.h" #include "sort.h" #include "util.h" #include "value.h" // constants static const int KillerNb = 2; static const int HistorySize = 12 * 64 /** 64*/; static const int HistoryMax = 16384; static const int TransScore = +32766; static const int GoodScore = +4000; static const int KillerScore = +4; static const int HistoryScore = -24000; static const int BadScore = -28000; static const int CODE_SIZE = 256; // macros #define HISTORY_INC(depth) ((depth)*(depth)) // types enum gen_t { GEN_ERROR, GEN_LEGAL_EVASION, GEN_TRANS, GEN_GOOD_CAPTURE, GEN_BAD_CAPTURE, GEN_KILLER, GEN_QUIET, GEN_EVASION_QS, GEN_CAPTURE_QS, GEN_CHECK_QS, GEN_END }; enum test_t { TEST_ERROR, TEST_NONE, TEST_LEGAL, TEST_TRANS_KILLER, TEST_GOOD_CAPTURE, TEST_BAD_CAPTURE, TEST_KILLER, TEST_QUIET, TEST_CAPTURE_QS, TEST_CHECK_QS }; // variables static int PosLegalEvasion; static int PosSEE; static int PosEvasionQS; static int PosCheckQS; static int PosCaptureQS; static int Code[CODE_SIZE]; static uint16 Killer[MaxThreads][HeightMax][KillerNb]; static uint16 History[MaxThreads][HistorySize]; static uint16 HistHit[MaxThreads][HistorySize]; static uint16 HistTot[MaxThreads][HistorySize]; // prototypes static void note_captures (list_t * list, const board_t * board); static void note_quiet_moves (list_t * list, const board_t * board, int ThreadId); static void note_moves_simple (list_t * list, const board_t * board); static void note_mvv_lva (list_t * list, const board_t * board); static int move_value (int move, const board_t * board, int height, int trans_killer, int ThreadId); static int capture_value (int move, const board_t * board); static int quiet_move_value (int move, const board_t * board, int ThreadId); static int move_value_simple (int move, const board_t * board); static int history_prob (int move, const board_t * board, int ThreadId); static bool capture_is_good (int move, const board_t * board); static int mvv_lva (int move, const board_t * board); static uint16 history_index (int move, const board_t * board); // functions // sort_init() void sort_init(int ThreadId) { int i, height; int pos; //static bool first_time = true; // killer for (height = 0; height < HeightMax; height++) { for (i = 0; i < KillerNb; i++) Killer[ThreadId][height][i] = MoveNone; } // history for (i = 0; i < HistorySize; i++) History[ThreadId][i] = 0; //if (first_time){ for (i = 0; i < HistorySize; i++) { HistHit[ThreadId][i] = 1; HistTot[ThreadId][i] = 1; } // first_time = false; //} // Code[] for (pos = 0; pos < CODE_SIZE; pos++) Code[pos] = GEN_ERROR; pos = 0; // main search PosLegalEvasion = pos; Code[pos++] = GEN_LEGAL_EVASION; Code[pos++] = GEN_END; PosSEE = pos; Code[pos++] = GEN_TRANS; Code[pos++] = GEN_GOOD_CAPTURE; Code[pos++] = GEN_KILLER; Code[pos++] = GEN_QUIET; Code[pos++] = GEN_BAD_CAPTURE; Code[pos++] = GEN_END; // quiescence search PosEvasionQS = pos; Code[pos++] = GEN_EVASION_QS; Code[pos++] = GEN_END; PosCheckQS = pos; Code[pos++] = GEN_CAPTURE_QS; Code[pos++] = GEN_CHECK_QS; Code[pos++] = GEN_END; PosCaptureQS = pos; Code[pos++] = GEN_CAPTURE_QS; Code[pos++] = GEN_END; ASSERT(posboard = board; sort->attack = attack; sort->depth = depth; sort->height = height; sort->capture_nb = 0; sort->trans_killer = trans_killer; sort->killer_1 = Killer[ThreadId][sort->height][0]; sort->killer_2 = Killer[ThreadId][sort->height][1]; if (ATTACK_IN_CHECK(sort->attack)) { gen_legal_evasions(sort->list,sort->board,sort->attack); note_moves(sort->list,sort->board,sort->height,sort->trans_killer,ThreadId); list_sort(sort->list); sort->gen = PosLegalEvasion + 1; sort->test = TEST_NONE; } else { // not in check LIST_CLEAR(sort->list); sort->gen = PosSEE; } sort->pos = 0; } // sort_next() int sort_next(sort_t * sort, int ThreadId) { int move; int gen; ASSERT(sort!=NULL); while (true) { while (sort->pos < LIST_SIZE(sort->list)) { // next move move = LIST_MOVE(sort->list,sort->pos); sort->value = 16384; // default score sort->valuePV = 16384; sort->pos++; ASSERT(move!=MoveNone); // test if (false) { } else if (sort->test == TEST_NONE) { // no-op } else if (sort->test == TEST_TRANS_KILLER) { if (!move_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_GOOD_CAPTURE) { ASSERT(move_is_tactical(move,sort->board)); if (move == sort->trans_killer) continue; if (!capture_is_good(move,sort->board)) { LIST_ADD(sort->bad,move); continue; } if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_BAD_CAPTURE) { ASSERT(move_is_tactical(move,sort->board)); ASSERT(!capture_is_good(move,sort->board)); ASSERT(move!=sort->trans_killer); if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_KILLER) { if (move == sort->trans_killer) continue; if (!quiet_is_pseudo(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; ASSERT(!move_is_tactical(move,sort->board)); } else if (sort->test == TEST_QUIET) { ASSERT(!move_is_tactical(move,sort->board)); if (move == sort->trans_killer) continue; if (move == sort->killer_1) continue; if (move == sort->killer_2) continue; if (!pseudo_is_legal(move,sort->board)) continue; sort->value = history_prob(move,sort->board,ThreadId); } else { ASSERT(false); return MoveNone; } ASSERT(pseudo_is_legal(move,sort->board)); return move; } // next stage gen = Code[sort->gen++]; if (false) { } else if (gen == GEN_TRANS) { LIST_CLEAR(sort->list); if (sort->trans_killer != MoveNone) LIST_ADD(sort->list,sort->trans_killer); sort->test = TEST_TRANS_KILLER; } else if (gen == GEN_GOOD_CAPTURE) { gen_captures(sort->list,sort->board); sort->capture_nb = LIST_SIZE(sort->list); note_mvv_lva(sort->list,sort->board); list_sort(sort->list); LIST_CLEAR(sort->bad); sort->test = TEST_GOOD_CAPTURE; } else if (gen == GEN_BAD_CAPTURE) { list_copy(sort->list,sort->bad); sort->test = TEST_BAD_CAPTURE; } else if (gen == GEN_KILLER) { LIST_CLEAR(sort->list); if (sort->killer_1 != MoveNone) LIST_ADD(sort->list,sort->killer_1); if (sort->killer_2 != MoveNone) LIST_ADD(sort->list,sort->killer_2); sort->test = TEST_KILLER; } else if (gen == GEN_QUIET) { gen_quiet_moves(sort->list,sort->board); note_quiet_moves(sort->list,sort->board,ThreadId); list_sort(sort->list); sort->test = TEST_QUIET; } else { ASSERT(gen==GEN_END); return MoveNone; } sort->pos = 0; } } // sort_init_qs() void sort_init_qs(sort_t * sort, board_t * board, const attack_t * attack, bool check) { ASSERT(sort!=NULL); ASSERT(board!=NULL); ASSERT(attack!=NULL); ASSERT(check==true||check==false); sort->board = board; sort->attack = attack; if (ATTACK_IN_CHECK(sort->attack)) { sort->gen = PosEvasionQS; } else if (check) { sort->gen = PosCheckQS; } else { sort->gen = PosCaptureQS; } LIST_CLEAR(sort->list); sort->pos = 0; } // sort_next_qs() int sort_next_qs(sort_t * sort) { int move; int gen; ASSERT(sort!=NULL); while (true) { while (sort->pos < LIST_SIZE(sort->list)) { // next move move = LIST_MOVE(sort->list,sort->pos); sort->pos++; ASSERT(move!=MoveNone); // test if (false) { } else if (sort->test == TEST_LEGAL) { if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_CAPTURE_QS) { ASSERT(move_is_tactical(move,sort->board)); if (!capture_is_good(move,sort->board)) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else if (sort->test == TEST_CHECK_QS) { ASSERT(!move_is_tactical(move,sort->board)); ASSERT(move_is_check(move,sort->board)); if (see_move(move,sort->board) < 0) continue; if (!pseudo_is_legal(move,sort->board)) continue; } else { ASSERT(false); return MoveNone; } ASSERT(pseudo_is_legal(move,sort->board)); return move; } // next stage gen = Code[sort->gen++]; if (false) { } else if (gen == GEN_EVASION_QS) { gen_pseudo_evasions(sort->list,sort->board,sort->attack); note_moves_simple(sort->list,sort->board); list_sort(sort->list); sort->test = TEST_LEGAL; } else if (gen == GEN_CAPTURE_QS) { gen_captures(sort->list,sort->board); note_mvv_lva(sort->list,sort->board); list_sort(sort->list); sort->test = TEST_CAPTURE_QS; } else if (gen == GEN_CHECK_QS) { gen_quiet_checks(sort->list,sort->board); sort->test = TEST_CHECK_QS; } else { ASSERT(gen==GEN_END); return MoveNone; } sort->pos = 0; } } // good_move() void good_move(int move, const board_t * board, int depth, int height, int ThreadId) { uint16 index; int i; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(depth_is_ok(depth)); ASSERT(height_is_ok(height)); if (move_is_tactical(move,board)) return; // killer if (Killer[ThreadId][height][0] != move) { Killer[ThreadId][height][1] = Killer[ThreadId][height][0]; Killer[ThreadId][height][0] = move; } ASSERT(Killer[ThreadId][height][0]==move); ASSERT(Killer[ThreadId][height][1]!=move); // history index = history_index(move,board); History[ThreadId][index] += HISTORY_INC(depth); if (History[ThreadId][index] >= HistoryMax) { for (i = 0; i < HistorySize; i++) { History[ThreadId][i] = (History[ThreadId][i] + 1) / 2; } } } // history_good() void history_good(int move, const board_t * board, int ThreadId) { uint16 index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); if (move_is_tactical(move,board)) return; // history index = history_index(move,board); HistHit[ThreadId][index]++; HistTot[ThreadId][index]++; if (HistTot[ThreadId][index] >= HistoryMax) { HistHit[ThreadId][index] = (HistHit[ThreadId][index] + 1) / 2; HistTot[ThreadId][index] = (HistTot[ThreadId][index] + 1) / 2; } ASSERT(HistHit[ThreadId][index]<=HistTot[ThreadId][index]); ASSERT(HistTot[ThreadId][index]= HistoryMax) { HistHit[ThreadId][index] = (HistHit[ThreadId][index] + 1) / 2; HistTot[ThreadId][index] = (HistTot[ThreadId][index] + 1) / 2; } ASSERT(HistHit[ThreadId][index]<=HistTot[ThreadId][index]); ASSERT(HistTot[ThreadId][index]= 2) { for (i = 0; i < size; i++) { move = LIST_MOVE(list,i); list->value[i] = move_value(move,board,height,trans_killer,ThreadId); } } } // note_captures() static void note_captures(list_t * list, const board_t * board) { int size; int i, move; ASSERT(list_is_ok(list)); ASSERT(board!=NULL); size = LIST_SIZE(list); if (size >= 2) { for (i = 0; i < size; i++) { move = LIST_MOVE(list,i); list->value[i] = capture_value(move,board); } } } // note_quiet_moves() static void note_quiet_moves(list_t * list, const board_t * board, int ThreadId) { int size; int i, move; ASSERT(list_is_ok(list)); ASSERT(board!=NULL); size = LIST_SIZE(list); if (size >= 2) { for (i = 0; i < size; i++) { move = LIST_MOVE(list,i); list->value[i] = quiet_move_value(move,board,ThreadId); } } } // note_moves_simple() static void note_moves_simple(list_t * list, const board_t * board) { int size; int i, move; ASSERT(list_is_ok(list)); ASSERT(board!=NULL); size = LIST_SIZE(list); if (size >= 2) { for (i = 0; i < size; i++) { move = LIST_MOVE(list,i); list->value[i] = move_value_simple(move,board); } } } // note_mvv_lva() static void note_mvv_lva(list_t * list, const board_t * board) { int size; int i, move; ASSERT(list_is_ok(list)); ASSERT(board!=NULL); size = LIST_SIZE(list); if (size >= 2) { for (i = 0; i < size; i++) { move = LIST_MOVE(list,i); list->value[i] = mvv_lva(move,board); } } } // move_value() static int move_value(int move, const board_t * board, int height, int trans_killer, int ThreadId) { int value; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(height_is_ok(height)); ASSERT(trans_killer==MoveNone||move_is_ok(trans_killer)); if (false) { } else if (move == trans_killer) { // transposition table killer value = TransScore; } else if (move_is_tactical(move,board)) { // capture or promote value = capture_value(move,board); } else if (move == Killer[ThreadId][height][0]) { // killer 1 value = KillerScore; } else if (move == Killer[ThreadId][height][1]) { // killer 2 value = KillerScore - 2; } else { // quiet move value = quiet_move_value(move,board,ThreadId); } return value; } // capture_value() static int capture_value(int move, const board_t * board) { int value; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); value = mvv_lva(move,board); if (capture_is_good(move,board)) { value += GoodScore; } else { value += BadScore; } ASSERT(value>=-30000&&value<=+30000); return value; } // quiet_move_value() static int quiet_move_value(int move, const board_t * board, int ThreadId) { int value; uint16 index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); index = history_index(move,board); value = HistoryScore + History[ThreadId][index]; ASSERT(value>=HistoryScore&&value<=KillerScore-4); return value; } // move_value_simple() static int move_value_simple(int move, const board_t * board) { int value; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); value = HistoryScore; if (move_is_tactical(move,board)) value = mvv_lva(move,board); return value; } // history_prob() static int history_prob(int move, const board_t * board, int ThreadId) { int value; uint16 index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); index = history_index(move,board); ASSERT(HistHit[ThreadId][index]<=HistTot[ThreadId][index]); ASSERT(HistTot[ThreadId][index]=0&&value<=16384); return value; } // capture_is_good() static bool capture_is_good(int move, const board_t * board) { int piece, capture; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); // special cases if (MOVE_IS_EN_PASSANT(move)) return true; if (move_is_under_promote(move)) return false; // REMOVE ME? // captures and queen promotes capture = board->square[MOVE_TO(move)]; if (capture != Empty) { // capture ASSERT(move_is_capture(move,board)); if (MOVE_IS_PROMOTE(move)) return true; // promote-capture piece = board->square[MOVE_FROM(move)]; if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true; } return see_move(move,board) >= 0; } // mvv_lva() static int mvv_lva(int move, const board_t * board) { int piece, capture, promote; int value; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); if (MOVE_IS_EN_PASSANT(move)) { // en-passant capture value = 5; // PxP } else if ((capture = board->square[MOVE_TO(move)]) != Empty) { // normal capture piece = board->square[MOVE_FROM(move)]; value = PIECE_ORDER(capture) * 6 - PIECE_ORDER(piece) + 5; ASSERT(value>=0&&value<30); } else { // promote ASSERT(MOVE_IS_PROMOTE(move)); promote = move_promote(move); value = PIECE_ORDER(promote) - 5; ASSERT(value>=-4&&value<0); } ASSERT(value>=-4&&value<+30); return value; } // history_index() static uint16 history_index(int move, const board_t * board) { uint16 index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move)); //index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * (64*64) + SQUARE_TO_64(MOVE_FROM(move)) * 64 + SQUARE_TO_64(MOVE_TO(move)); ASSERT(index>=0&&index $@ include .depend toga2-3.0.0.1SE1/src/see.h0000644000175000017500000000044511125217316014276 0ustar oliveroliver // see.h #ifndef SEE_H #define SEE_H // includes #include "board.h" #include "util.h" // functions extern int see_move (int move, const board_t * board); extern int see_square (const board_t * board, int to, int colour); #endif // !defined SEE_H // end of see.h toga2-3.0.0.1SE1/src/fen.cpp0000644000175000017500000001361411125217320014622 0ustar oliveroliver // fen.cpp // includes #include #include #include #include "board.h" #include "colour.h" #include "fen.h" #include "piece.h" #include "square.h" #include "util.h" // "constants" const char * const StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; // variables static const bool Strict = false; // functions // board_from_fen() void board_from_fen(board_t * board, const char fen[]) { int pos; int file, rank, sq; int c; int i, len; int piece; int pawn; ASSERT(board!=NULL); ASSERT(fen!=NULL); board_clear(board); pos = 0; c = fen[pos]; // piece placement for (rank = Rank8; rank >= Rank1; rank--) { for (file = FileA; file <= FileH;) { if (c >= '1' && c <= '8') { // empty square(s) len = c - '0'; for (i = 0; i < len; i++) { if (file > FileH) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); board->square[SQUARE_MAKE(file,rank)] = Empty; file++; } } else { // piece piece = piece_from_char(c); if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); board->square[SQUARE_MAKE(file,rank)] = piece; file++; } c = fen[++pos]; } if (rank > Rank1) { if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; } } // active colour if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; switch (c) { case 'w': board->turn = White; break; case 'b': board->turn = Black; break; default: my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); break; } c = fen[++pos]; // castling if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; board->flags = FlagsNone; if (c == '-') { // no castling rights c = fen[++pos]; } else { if (c == 'K') { if (board->square[E1] == WK && board->square[H1] == WR) board->flags |= FlagsWhiteKingCastle; c = fen[++pos]; } if (c == 'Q') { if (board->square[E1] == WK && board->square[A1] == WR) board->flags |= FlagsWhiteQueenCastle; c = fen[++pos]; } if (c == 'k') { if (board->square[E8] == BK && board->square[H8] == BR) board->flags |= FlagsBlackKingCastle; c = fen[++pos]; } if (c == 'q') { if (board->square[E8] == BK && board->square[A8] == BR) board->flags |= FlagsBlackQueenCastle; c = fen[++pos]; } } // en-passant if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; if (c == '-') { // no en-passant sq = SquareNone; c = fen[++pos]; } else { if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); file = file_from_char(c); c = fen[++pos]; if (c != (COLOUR_IS_WHITE(board->turn) ? '6' : '3')) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); rank = rank_from_char(c); c = fen[++pos]; sq = SQUARE_MAKE(file,rank); pawn = SQUARE_EP_DUAL(sq); if (board->square[sq] != Empty || board->square[pawn] != PAWN_MAKE(COLOUR_OPP(board->turn)) || (board->square[pawn-1] != PAWN_MAKE(board->turn) && board->square[pawn+1] != PAWN_MAKE(board->turn))) { sq = SquareNone; } } board->ep_square = sq; // halfmove clock board->ply_nb = 0; if (c != ' ') { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } c = fen[++pos]; if (!isdigit(c)) { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } board->ply_nb = atoi(&fen[pos]); // board update update: board_init_list(board); } // board_to_fen() bool board_to_fen(const board_t * board, char fen[], int size) { int pos; int file, rank; int sq, piece; int c; int len; ASSERT(board!=NULL); ASSERT(fen!=NULL); ASSERT(size>=92); // init if (size < 92) return false; pos = 0; // piece placement for (rank = Rank8; rank >= Rank1; rank--) { for (file = FileA; file <= FileH;) { sq = SQUARE_MAKE(file,rank); piece = board->square[sq]; ASSERT(piece==Empty||piece_is_ok(piece)); if (piece == Empty) { len = 0; for (; file <= FileH && board->square[SQUARE_MAKE(file,rank)] == Empty; file++) { len++; } ASSERT(len>=1&&len<=8); c = '0' + len; } else { c = piece_to_char(piece); file++; } fen[pos++] = c; } fen[pos++] = '/'; } fen[pos-1] = ' '; // HACK: remove the last '/' // active colour fen[pos++] = (COLOUR_IS_WHITE(board->turn)) ? 'w' : 'b'; fen[pos++] = ' '; // castling if (board->flags == FlagsNone) { fen[pos++] = '-'; } else { if ((board->flags & FlagsWhiteKingCastle) != 0) fen[pos++] = 'K'; if ((board->flags & FlagsWhiteQueenCastle) != 0) fen[pos++] = 'Q'; if ((board->flags & FlagsBlackKingCastle) != 0) fen[pos++] = 'k'; if ((board->flags & FlagsBlackQueenCastle) != 0) fen[pos++] = 'q'; } fen[pos++] = ' '; // en-passant if (board->ep_square == SquareNone) { fen[pos++] = '-'; } else { square_to_string(board->ep_square,&fen[pos],3); pos += 2; } fen[pos++] = ' '; // halfmove clock sprintf(&fen[pos],"%d 1",board->ply_nb); return true; } // end of fen.cpp toga2-3.0.0.1SE1/src/posix.cpp0000644000175000017500000001023311125217312015207 0ustar oliveroliver // posix.cpp // includes #include #include // REMOVE ME? #include #include #include #if defined(_WIN32) || defined(_WIN64) # include #else // assume POSIX # include // # include # include # include # include #endif #include "posix.h" #include "util.h" // constants static const bool UseDebug = false; // prototypes #if !defined(_WIN32) && !defined(_WIN64) static double duration (const struct timeval * tv); #endif // functions // input_available() bool input_available() { #if defined(_WIN32) || defined(_WIN64) static bool init = false, is_pipe; static HANDLE stdin_h; DWORD val, error; // val = 0; // needed to make the compiler happy? // have a look at the "local" buffer first, *this time before init (no idea if it helps)* if (UseDebug && !init) printf("info string init=%d stdin->_cnt=%d\n",int(init),stdin->_cnt); if (stdin->_cnt > 0) return true; // HACK: assumes FILE internals // input init (only done once) if (!init) { init = true; stdin_h = GetStdHandle(STD_INPUT_HANDLE); if (UseDebug && (stdin_h == NULL || stdin_h == INVALID_HANDLE_VALUE)) { error = GetLastError(); printf("info string GetStdHandle() failed, error=%d\n",error); } is_pipe = !GetConsoleMode(stdin_h,&val); // HACK: assumes pipe on failure if (UseDebug) printf("info string init=%d is_pipe=%d\n",int(init),int(is_pipe)); if (UseDebug && is_pipe) { // GetConsoleMode() failed, everybody assumes pipe then error = GetLastError(); printf("info string GetConsoleMode() failed, error=%d\n",error); } if (!is_pipe) { SetConsoleMode(stdin_h,val&~(ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT)); FlushConsoleInputBuffer(stdin_h); // no idea if we can lose data doing this } } // different polling depending on input type // does this code work at all for pipes? if (is_pipe) { if (!PeekNamedPipe(stdin_h,NULL,0,NULL,&val,NULL)) { if (UseDebug) { // PeekNamedPipe() failed, everybody assumes EOF then error = GetLastError(); printf("info string PeekNamedPipe() failed, error=%d\n",error); } return true; // HACK: assumes EOF on failure } if (UseDebug && val < 0) printf("info string PeekNamedPipe(): val=%d\n",val); return val > 0; // != 0??? } else { GetNumberOfConsoleInputEvents(stdin_h,&val); return val > 1; // no idea why 1 } return false; #else // assume POSIX int val; fd_set set[1]; struct timeval time_val[1]; FD_ZERO(set); FD_SET(STDIN_FILENO,set); time_val->tv_sec = 0; time_val->tv_usec = 0; val = select(STDIN_FILENO+1,set,NULL,NULL,time_val); if (val == -1 && errno != EINTR) { my_fatal("input_available(): select(): %s\n",strerror(errno)); } return val > 0; #endif } // now_real() double now_real() { #if defined(_WIN32) || defined(_WIN64) return double(GetTickCount()) / 1000.0; #else // assume POSIX struct timeval tv[1]; struct timezone tz[1]; tz->tz_minuteswest = 0; tz->tz_dsttime = 0; // DST_NONE not declared in linux if (gettimeofday(tv,tz) == -1) { // tz needed at all? my_fatal("now_real(): gettimeofday(): %s\n",strerror(errno)); } return duration(tv); #endif } // now_cpu() double now_cpu() { #if defined(_WIN32) || defined(_WIN64) return double(clock()) / double(CLOCKS_PER_SEC); // OK if CLOCKS_PER_SEC is small enough #else // assume POSIX struct rusage ru[1]; if (getrusage(RUSAGE_SELF,ru) == -1) { my_fatal("now_cpu(): getrusage(): %s\n",strerror(errno)); } return duration(&ru->ru_utime); #endif } // duration() #if !defined(_WIN32) && !defined(_WIN64) static double duration(const struct timeval * tv) { ASSERT(tv!=NULL); return double(tv->tv_sec) + double(tv->tv_usec) * 1E-6; } #endif // end of posix.cpp toga2-3.0.0.1SE1/src/move_check.cpp0000644000175000017500000002174311125217316016164 0ustar oliveroliver // move_check.cpp // includes #include "attack.h" #include "colour.h" #include "fen.h" #include "list.h" #include "move.h" #include "move_check.h" #include "move_do.h" #include "move_gen.h" #include "piece.h" #include "square.h" #include "util.h" // prototypes static void add_quiet_checks (list_t * list, const board_t * board); static void add_castle_checks (list_t * list, board_t * board); static void add_check (list_t * list, int move, board_t * board); static void find_pins (int list[], const board_t * board); // functions // gen_quiet_checks() void gen_quiet_checks(list_t * list, board_t * board) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); LIST_CLEAR(list); add_quiet_checks(list,board); add_castle_checks(list,board); // debug ASSERT(list_is_ok(list)); } // add_quiet_checks() static void add_quiet_checks(list_t * list, const board_t * board) { int me, opp; int king; const sq_t * ptr, * ptr_2; int from, to, sq; int piece; const inc_t * inc_ptr; int inc; int pawn; int rank; int pin[8+1]; ASSERT(list!=NULL); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); find_pins(pin,board); // indirect checks for (ptr = pin; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; ASSERT(is_pinned(board,from,opp)); if (PIECE_IS_PAWN(piece)) { inc = PAWN_MOVE_INC(me); rank = PAWN_RANK(from,me); if (rank != Rank7) { // promotes are generated with captures to = from + inc; if (board->square[to] == Empty) { if (DELTA_INC_LINE(to-king) != DELTA_INC_LINE(from-king)) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); if (rank == Rank2) { to = from + (2*inc); if (board->square[to] == Empty) { ASSERT(DELTA_INC_LINE(to-king)!=DELTA_INC_LINE(from-king)); ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } } else if (PIECE_IS_SLIDER(piece)) { for (inc_ptr = PIECE_INC(piece); (inc=*inc_ptr) != IncNone; inc_ptr++) { for (to = from+inc; board->square[to] == Empty; to += inc) { ASSERT(DELTA_INC_LINE(to-king)!=DELTA_INC_LINE(from-king)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } else { for (inc_ptr = PIECE_INC(piece); (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; if (board->square[to] == Empty) { if (DELTA_INC_LINE(to-king) != DELTA_INC_LINE(from-king)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } // piece direct checks for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king for (ptr_2 = pin; (sq=*ptr_2) != SquareNone; ptr_2++) { if (sq == from) goto next_piece; } ASSERT(!is_pinned(board,from,opp)); piece = board->square[from]; inc_ptr = PIECE_INC(piece); if (PIECE_IS_SLIDER(piece)) { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { for (to = from+inc; board->square[to] == Empty; to += inc) { if (PIECE_ATTACK(board,piece,to,king)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } else { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; if (board->square[to] == Empty) { if (PSEUDO_ATTACK(piece,king-to)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } next_piece: ; } // pawn direct checks inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); to = king - (inc-1); ASSERT(PSEUDO_ATTACK(pawn,king-to)); from = to - inc; if (board->square[from] == pawn) { if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } else { from = to - (2*inc); if (board->square[from] == pawn) { if (PAWN_RANK(from,me) == Rank2 && board->square[to] == Empty && board->square[from+inc] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } to = king - (inc+1); ASSERT(PSEUDO_ATTACK(pawn,king-to)); from = to - inc; if (board->square[from] == pawn) { if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } else { from = to - (2*inc); if (board->square[from] == pawn) { if (PAWN_RANK(from,me) == Rank2 && board->square[to] == Empty && board->square[from+inc] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } // add_castle_checks() static void add_castle_checks(list_t * list, board_t * board) { ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); if (COLOUR_IS_WHITE(board->turn)) { if ((board->flags & FlagsWhiteKingCastle) != 0 && board->square[F1] == Empty && board->square[G1] == Empty && !is_attacked(board,F1,Black)) { add_check(list,MOVE_MAKE_FLAGS(E1,G1,MoveCastle),board); } if ((board->flags & FlagsWhiteQueenCastle) != 0 && board->square[D1] == Empty && board->square[C1] == Empty && board->square[B1] == Empty && !is_attacked(board,D1,Black)) { add_check(list,MOVE_MAKE_FLAGS(E1,C1,MoveCastle),board); } } else { // black if ((board->flags & FlagsBlackKingCastle) != 0 && board->square[F8] == Empty && board->square[G8] == Empty && !is_attacked(board,F8,White)) { add_check(list,MOVE_MAKE_FLAGS(E8,G8,MoveCastle),board); } if ((board->flags & FlagsBlackQueenCastle) != 0 && board->square[D8] == Empty && board->square[C8] == Empty && board->square[B8] == Empty && !is_attacked(board,D8,White)) { add_check(list,MOVE_MAKE_FLAGS(E8,C8,MoveCastle),board); } } } // add_check() static void add_check(list_t * list, int move, board_t * board) { undo_t undo[1]; ASSERT(list!=NULL); ASSERT(move_is_ok(move)); ASSERT(board!=NULL); move_do(board,move,undo); if (IS_IN_CHECK(board,board->turn)) LIST_ADD(list,move); move_undo(board,move,undo); } // move_is_check() bool move_is_check(int move, board_t * board) { undo_t undo[1]; bool check; int me, opp, king; int from, to, piece; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // slow test for complex moves if (MOVE_IS_SPECIAL(move)) { move_do(board,move,undo); check = IS_IN_CHECK(board,board->turn); move_undo(board,move,undo); return check; } // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // direct check if (PIECE_ATTACK(board,piece,to,king)) return true; // indirect check if (is_pinned(board,from,opp) && DELTA_INC_LINE(king-to) != DELTA_INC_LINE(king-from)) { return true; } return false; } // find_pins() static void find_pins(int list[], const board_t * board) { int me, opp; int king; const sq_t * ptr; int from; int piece; int delta; int inc; int sq; int capture; int pin; ASSERT(list!=NULL); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; delta = king - from; ASSERT(delta_is_ok(delta)); if (PSEUDO_ATTACK(piece,delta)) { ASSERT(PIECE_IS_SLIDER(piece)); inc = DELTA_INC_LINE(delta); ASSERT(inc!=IncNone); ASSERT(SLIDER_ATTACK(piece,inc)); sq = from; do sq += inc; while ((capture=board->square[sq]) == Empty); ASSERT(sq!=king); if (COLOUR_IS(capture,me)) { pin = sq; do sq += inc; while (board->square[sq] == Empty); if (sq == king) *list++ = pin; } } } *list = SquareNone; } // end of move_check.cpp toga2-3.0.0.1SE1/src/see.cpp0000644000175000017500000002033511125217314014627 0ustar oliveroliver // see.cpp // includes #include "attack.h" #include "board.h" #include "colour.h" #include "move.h" #include "piece.h" #include "see.h" #include "util.h" #include "value.h" // macros #define ALIST_CLEAR(alist) ((alist)->size=0) // types struct alist_t { int size; int square[15]; }; struct alists_t { alist_t alist[ColourNb][1]; }; // prototypes static int see_rec (alists_t * alists, const board_t * board, int colour, int to, int piece_value); static void alist_build (alist_t * alist, const board_t * board, int to, int colour); static void alists_hidden (alists_t * alists, const board_t * board, int from, int to); static void alist_clear (alist_t * alist); static void alist_add (alist_t * alist, int square, const board_t * board); static void alist_remove (alist_t * alist, int pos); static int alist_pop (alist_t * alist, const board_t * board); // functions // see_move() int see_move(int move, const board_t * board) { int att, def; int from, to; alists_t alists[1]; int value, piece_value; int piece, capture; alist_t * alist; int pos; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // init from = MOVE_FROM(move); to = MOVE_TO(move); // move the piece piece_value = 0; piece = board->square[from]; ASSERT(piece_is_ok(piece)); att = PIECE_COLOUR(piece); def = COLOUR_OPP(att); // promote if (MOVE_IS_PROMOTE(move)) { ASSERT(PIECE_IS_PAWN(piece)); piece = move_promote(move); ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,att)); } piece_value += VALUE_PIECE(piece); // clear attacker lists ALIST_CLEAR(alists->alist[Black]); ALIST_CLEAR(alists->alist[White]); // find hidden attackers alists_hidden(alists,board,from,to); // capture the piece value = 0; capture = board->square[to]; if (capture != Empty) { ASSERT(piece_is_ok(capture)); ASSERT(COLOUR_IS(capture,def)); value += VALUE_PIECE(capture); } // promote if (MOVE_IS_PROMOTE(move)) { value += VALUE_PIECE(piece) - ValuePawn; } // en-passant if (MOVE_IS_EN_PASSANT(move)) { ASSERT(value==0); ASSERT(PIECE_IS_PAWN(board->square[SQUARE_EP_DUAL(to)])); value += ValuePawn; alists_hidden(alists,board,SQUARE_EP_DUAL(to),to); } // build defender list alist = alists->alist[def]; alist_build(alist,board,to,def); if (alist->size == 0) return value; // no defender => stop SEE // build attacker list alist = alists->alist[att]; alist_build(alist,board,to,att); // remove the moved piece (if it's an attacker) for (pos = 0; pos < alist->size && alist->square[pos] != from; pos++) ; if (pos < alist->size) alist_remove(alist,pos); // SEE search value -= see_rec(alists,board,def,to,piece_value); return value; } // see_square() int see_square(const board_t * board, int to, int colour) { int att, def; alists_t alists[1]; alist_t * alist; int piece_value; int piece; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(COLOUR_IS_OK(colour)); ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(colour))); // build attacker list att = colour; alist = alists->alist[att]; ALIST_CLEAR(alist); alist_build(alist,board,to,att); if (alist->size == 0) return 0; // no attacker => stop SEE // build defender list def = COLOUR_OPP(att); alist = alists->alist[def]; ALIST_CLEAR(alist); alist_build(alist,board,to,def); // captured piece piece = board->square[to]; ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,def)); piece_value = VALUE_PIECE(piece); // SEE search return see_rec(alists,board,att,to,piece_value); } // see_rec() static int see_rec(alists_t * alists, const board_t * board, int colour, int to, int piece_value) { int from, piece; int value; ASSERT(alists!=NULL); ASSERT(board!=NULL); ASSERT(COLOUR_IS_OK(colour)); ASSERT(SQUARE_IS_OK(to)); ASSERT(piece_value>0); // find the least valuable attacker from = alist_pop(alists->alist[colour],board); if (from == SquareNone) return 0; // no more attackers // find hidden attackers alists_hidden(alists,board,from,to); // calculate the capture value value = +piece_value; // captured piece if (value == ValueKing) return value; // do not allow an answer to a king capture piece = board->square[from]; ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,colour)); piece_value = VALUE_PIECE(piece); // promote if (piece_value == ValuePawn && SQUARE_IS_PROMOTE(to)) { // HACK: PIECE_IS_PAWN(piece) ASSERT(PIECE_IS_PAWN(piece)); piece_value = ValueQueen; value += ValueQueen - ValuePawn; } value -= see_rec(alists,board,COLOUR_OPP(colour),to,piece_value); if (value < 0) value = 0; return value; } // alist_build() static void alist_build(alist_t * alist, const board_t * board, int to, int colour) { const sq_t * ptr; int from; int piece; int delta; int inc; int sq; int pawn; ASSERT(alist!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(COLOUR_IS_OK(colour)); // piece attacks for (ptr = &board->piece[colour][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; delta = to - from; if (PSEUDO_ATTACK(piece,delta)) { inc = DELTA_INC_ALL(delta); ASSERT(inc!=IncNone); sq = from; do { sq += inc; if (sq == to) { // attack alist_add(alist,from,board); break; } } while (board->square[sq] == Empty); } } // pawn attacks inc = PAWN_MOVE_INC(colour); pawn = PAWN_MAKE(colour); from = to - (inc-1); if (board->square[from] == pawn) alist_add(alist,from,board); from = to - (inc+1); if (board->square[from] == pawn) alist_add(alist,from,board); } // alists_hidden() static void alists_hidden(alists_t * alists, const board_t * board, int from, int to) { int inc; int sq, piece; ASSERT(alists!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); inc = DELTA_INC_LINE(to-from); if (inc != IncNone) { // line sq = from; do sq -= inc; while ((piece=board->square[sq]) == Empty); if (SLIDER_ATTACK(piece,inc)) { ASSERT(piece_is_ok(piece)); ASSERT(PIECE_IS_SLIDER(piece)); alist_add(alists->alist[PIECE_COLOUR(piece)],sq,board); } } } // alist_clear() static void alist_clear(alist_t * alist) { ASSERT(alist!=NULL); alist->size = 0; } // alist_add() static void alist_add(alist_t * alist, int square, const board_t * board) { int piece; int size, pos; ASSERT(alist!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(board!=NULL); // insert in MV order piece = board->square[square]; size = ++alist->size; // HACK ASSERT(size>0&&size<16); for (pos = size-1; pos > 0 && piece > board->square[alist->square[pos-1]]; pos--) { // HACK ASSERT(pos>0&&possquare[pos] = alist->square[pos-1]; } ASSERT(pos>=0&&possquare[pos] = square; } // alist_remove() static void alist_remove(alist_t * alist, int pos) { int size, i; ASSERT(alist!=NULL); ASSERT(pos>=0&&possize); size = alist->size--; // HACK ASSERT(size>=1); ASSERT(pos>=0&&pos=0&&isquare[i] = alist->square[i+1]; } } // alist_pop() static int alist_pop(alist_t * alist, const board_t * board) { int sq; int size; ASSERT(alist!=NULL); ASSERT(board!=NULL); sq = SquareNone; size = alist->size; if (size != 0) { size--; ASSERT(size>=0); sq = alist->square[size]; alist->size = size; } return sq; } // end of see.cpp toga2-3.0.0.1SE1/src/vector.cpp0000644000175000017500000000224711125217322015356 0ustar oliveroliver // vector.cpp // includes #include "piece.h" #include "square.h" #include "util.h" #include "vector.h" // variables int Distance[DeltaNb]; // functions void vector_init() { int delta; int x, y; int dist, tmp; // Distance[] for (delta = 0; delta < DeltaNb; delta++) Distance[delta] = -1; for (y = -7; y <= +7; y++) { for (x = -7; x <= +7; x++) { delta = y * 16 + x; ASSERT(delta_is_ok(delta)); dist = 0; tmp = x; if (tmp < 0) tmp = -tmp; if (tmp > dist) dist = tmp; tmp = y; if (tmp < 0) tmp = -tmp; if (tmp > dist) dist = tmp; Distance[DeltaOffset+delta] = dist; } } } // delta_is_ok() bool delta_is_ok(int delta) { if (delta < -119 || delta > +119) return false; if ((delta & 0xF) == 8) return false; // HACK: delta % 16 would be ill-defined for negative numbers return true; } // inc_is_ok() bool inc_is_ok(int inc) { int dir; for (dir = 0; dir < 8; dir++) { if (KingInc[dir] == inc) return true; } return false; } // end of vector.cpp toga2-3.0.0.1SE1/src/values.h0000644000175000017500000000107011125213416015011 0ustar oliveroliver// values.h #ifndef VALUE_H #define VALUE_H // macros #define VALUE_MATE(height) (-30000+(height)) #define VALUE_PIECE(piece) (value_piece[piece]) // variables extern int value_piece[256]; // functions extern void value_init(); extern bool value_is_ok(int value); extern bool range_is_ok(int min, int max); extern bool value_is_mate(int value); extern int value_to_trans(int value, int height); extern int value_from_trans(int value, int height); extern int value_to_mate(int value); #endif // !defined VALUE_H // end of values.h toga2-3.0.0.1SE1/src/random.h0000644000175000017500000000053411125217314014777 0ustar oliveroliver // random.h #ifndef RANDOM_H #define RANDOM_H // includes #include "util.h" // constants const int RandomNb = 781; // macros #define RANDOM_64(n) (Random64[n]) // "constants" extern const uint64 Random64[RandomNb]; // functions extern void random_init (); #endif // !defined RANDOM_H // end of random.h toga2-3.0.0.1SE1/src/CHANGELOG0000644000175000017500000000062011125217324014555 0ustar oliveroliver22/10/2008 - added LICENSE file taken from http://www.superchessengine.com/toga_ii.htm - added COPYING file - fix for small opening book handling bug; see http://www.computerchess.info/tdbb/phpBB3/viewtopic.php?f=9&t=177 - eliminated use of sem_init and friends; these do not work properly on MACOSX; see http://64.68.157.89/forum/viewtopic.php?t=24108&postdays=0&postorder=asc&topic_view=&start=30 toga2-3.0.0.1SE1/src/recog.h0000644000175000017500000000036011125217324014614 0ustar oliveroliver // recog.h #ifndef RECOG_H #define RECOG_H // includes #include "board.h" #include "util.h" // functions extern bool recog_draw (const board_t * board, int ThreadId); #endif // !defined RECOG_H // end of recog.h toga2-3.0.0.1SE1/src/move.h0000644000175000017500000000411711125217322014465 0ustar oliveroliver // move.h #ifndef MOVE_H #define MOVE_H // includes #include "board.h" #include "util.h" // constants const int MoveNone = 0; // HACK: a1a1 cannot be a legal move const int MoveNull = 11; // HACK: a1d2 cannot be a legal move const int MoveNormal = 0 << 14; const int MoveCastle = 1 << 14; const int MovePromote = 2 << 14; const int MoveEnPassant = 3 << 14; const int MoveFlags = 3 << 14; const int MovePromoteKnight = MovePromote | (0 << 12); const int MovePromoteBishop = MovePromote | (1 << 12); const int MovePromoteRook = MovePromote | (2 << 12); const int MovePromoteQueen = MovePromote | (3 << 12); const int MoveAllFlags = 0xF << 12; const char NullMoveString[] = "null"; // "0000" in UCI // macros #define MOVE_MAKE(from,to) ((SQUARE_TO_64(from)<<6)|SQUARE_TO_64(to)) #define MOVE_MAKE_FLAGS(from,to,flags) ((SQUARE_TO_64(from)<<6)|SQUARE_TO_64(to)|(flags)) #define MOVE_FROM(move) (SQUARE_FROM_64(((move)>>6)&077)) #define MOVE_TO(move) (SQUARE_FROM_64((move)&077)) #define MOVE_IS_SPECIAL(move) (((move)&MoveFlags)!=MoveNormal) #define MOVE_IS_PROMOTE(move) (((move)&MoveFlags)==MovePromote) #define MOVE_IS_EN_PASSANT(move) (((move)&MoveFlags)==MoveEnPassant) #define MOVE_IS_CASTLE(move) (((move)&MoveFlags)==MoveCastle) #define MOVE_PIECE(move,board) ((board)->square[MOVE_FROM(move)]) // types typedef uint16 mv_t; // functions extern bool move_is_ok (int move); extern int move_promote (int move); extern int move_order (int move); extern bool move_is_capture (int move, const board_t * board); extern bool move_is_under_promote (int move); extern bool move_is_tactical (int move, const board_t * board); extern int move_capture (int move, const board_t * board); extern bool move_to_string (int move, char string[], int size); extern int move_from_string (const char string[], const board_t * board); #endif // !defined MOVE_H // end of move.h toga2-3.0.0.1SE1/src/readme.txt0000644000175000017500000001171612120152452015345 0ustar oliveroliver Brief Description ------------------------ TOGA II 3.0 - This development of Toga is by Jerry Donald - The code was based on Toga II 2.0 by Fabien Letouzey, Thomas Gaksch, Jerry Donald and Chris Formula - Thanks to Denis Mendoza for the compile support - Thanks to Thomas Gaksch and Fabien Letouzey for the Fruit/TogaII source code - Thanks to Shaun Brewer for the test support Changes: - Multi-PV fixed - Aspiration windows - Hash table used in quiescent search (for lookup as well as store) - LMR improved (thanks to the authors of Stockfish and Protector) - TT avoid null-move flag - New Endgame Knowledge - Improved Mobility Evaluation (Ben Tennison) - Piece Combo (QN vs QB) adjustment TOGA II 2.0 - This development of Toga is by Jerry Donald - The code was based on Toga II 1.4.1SE by Fabien LetouzeyThomas Gaksch and Chris Formula - Thanks to Denis Mendoza for the compile support - Thanks to Thomas Gaksch and Fabien Letouzey for the Fruit/TogaII source code - Thanks to Shaun Brewer for the test support Changes: - Futility Margin is now dependent on played move count - Razoring full_quiescence() bounds fixed (thanks to Lucas Braesch) - Several eval() bounds fixed - Improved Pawn Shelter - Improved Knight Outpost - Improved Bishop Mobility - New Endgame Material Adjustments - Piece Values tweaked - Egbb bugfix (Teemu Pudas) TOGA II 1.4.1SE - This is an experimental engine by Chris Formula - The code was based on Toga II 1.4beta5c by Thomas Gaksch - Changes were an extended version of settings implemented in Toga II 3.1.2SE - Improved search efficiency - Thanks to Thomas Gaksch and Fabien Letouzey for the Fruit/TogaII source code - Thanks to Shaun Brewer for the test support - Thanks to Denis Mendoza for the compile support TOGA II 1.4 BETA5C - THIS VERSION is only a TEST VERSION. - For mp support a simple shared hashtable is used. MultiPV is not working with this beta. - The number of threads must be set before compiling in search.h. - Thanks a lot to Shaun Brewer, Dieter Eberle, Chris Formula, Denis Mendoza, Alessandro Scotti, Tord Romstad and much much more. - Without their help i wouldn´t be able to increase the playing strength, compared to Fruit 2.1. Legal Details ------------------- Toga II 1.3x4 (beta version) based on Fruit 2.1 by Fabien Letouzey. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See the file "copying.txt" for details. General ----------- Toga II 1.3x4 based on Fruit is a UCI-only chess engine. This distribution comes up only with Windows executable and platform-independent source code. Official distribution -------------------------- You can download the GNU GPL Package (incl. sources) with Toga II based on Fruit at: http://www.superchessengine.com/ or send an email to togaII@gmx.de Version ----------- Toga II 1.3x4 based on Fruit 2.1 Following changes and extensions made: - improved history pruning - improved futility pruning - improved lazy evaluation - new evaluation features (outpost knight etc.) - MultiPV Mode New in 1.2 - more pruning - more extensions - new settings by Dieter Eberle New in 1.2.1 - new settings - some minor bugfixes new in 1.3x4 - changes in eval - changes in search - Endgame bitbases by Daniel Shawul (Scorpio) new 1.3x4b - bugfix of the endgame bitbases with help from Daniel Shawul A very big thank to Daniel Shawul for sharing his great endgame bitbases and his dll. EGBBs ----- Toga uses the Scorpio endgame bitbases upto 5 pieces. Installation ------------ First You have to download the 5men bitbases from Leo Dijksman's WBEC site http://www.wbec-ridderkerk.nl . The egbbs are 340mb in size. Then put them anywhere in your computer. The default path is c:\egbb\ but you can change this in the uci options. The egbbdll.dll must be in the same folder as the bitbase files. Thanks Fabien Letouzey for the great source code of the program Fruit 2.1. Special thanks to Dieter Eberle, Karl-Heinz Söntges, Shaun Brewer for testing Beta Versions. A big thank to Dieter Eberle for his setting. Orlando Mouchel for bugfixes and new ideas. Wilhelm Hudetz for the Logo. Without their help i wouldn´t be able to increase the playing strenght, compared to Fruit 2.1, by about 100 Elo. Thomas Gaksch toga2-3.0.0.1SE1/src/book.h0000644000175000017500000000050511125217320014444 0ustar oliveroliver // book.h #ifndef BOOK_H #define BOOK_H // includes #include "board.h" #include "util.h" // functions extern void book_init (); extern void book_open (const char file_name[]); extern void book_close (); extern int book_move (board_t * board); #endif // !defined BOOK_H // end of book.h toga2-3.0.0.1SE1/src/move.cpp0000644000175000017500000000774211125217314015030 0ustar oliveroliver // move.cpp // includes #include #include #include "attack.h" #include "colour.h" #include "list.h" #include "move.h" #include "move_do.h" #include "move_gen.h" #include "piece.h" #include "square.h" #include "util.h" // constants static const int PromotePiece[4] = { Knight64, Bishop64, Rook64, Queen64 }; // functions // move_is_ok() bool move_is_ok(int move) { if (move < 0 || move >= 65536) return false; if (move == MoveNone) return false; if (move == MoveNull) return false; return true; } // move_promote() int move_promote(int move) { int code, piece; ASSERT(move_is_ok(move)); ASSERT(MOVE_IS_PROMOTE(move)); code = (move >> 12) & 3; piece = PromotePiece[code]; if (SQUARE_RANK(MOVE_TO(move)) == Rank8) { piece |= WhiteFlag; } else { ASSERT(SQUARE_RANK(MOVE_TO(move))==Rank1); piece |= BlackFlag; } ASSERT(piece_is_ok(piece)); return piece; } // move_order() int move_order(int move) { ASSERT(move_is_ok(move)); return ((move & 07777) << 2) | ((move >> 12) & 3); } // move_is_capture() bool move_is_capture(int move, const board_t * board) { ASSERT(move_is_ok(move)); ASSERT(board!=NULL); return MOVE_IS_EN_PASSANT(move) || board->square[MOVE_TO(move)] != Empty; } // move_is_under_promote() bool move_is_under_promote(int move) { ASSERT(move_is_ok(move)); return MOVE_IS_PROMOTE(move) && (move & MoveAllFlags) != MovePromoteQueen; } // move_is_tactical() bool move_is_tactical(int move, const board_t * board) { ASSERT(move_is_ok(move)); ASSERT(board!=NULL); return (move & (1 << 15)) != 0 || board->square[MOVE_TO(move)] != Empty; // HACK } // move_capture() int move_capture(int move, const board_t * board) { ASSERT(move_is_ok(move)); ASSERT(board!=NULL); if (MOVE_IS_EN_PASSANT(move)) { return PAWN_OPP(board->square[MOVE_FROM(move)]); } return board->square[MOVE_TO(move)]; } // move_to_string() bool move_to_string(int move, char string[], int size) { ASSERT(move==MoveNull||move_is_ok(move)); ASSERT(string!=NULL); ASSERT(size>=6); if (size < 6) return false; // null move if (move == MoveNull) { strcpy(string,NullMoveString); return true; } // normal moves square_to_string(MOVE_FROM(move),&string[0],3); square_to_string(MOVE_TO(move),&string[2],3); ASSERT(strlen(string)==4); // promotes if (MOVE_IS_PROMOTE(move)) { string[4] = tolower(piece_to_char(move_promote(move))); string[5] = '\0'; } return true; } // move_from_string() int move_from_string(const char string[], const board_t * board) { char tmp_string[3]; int from, to; int move; int piece, delta; ASSERT(string!=NULL); ASSERT(board!=NULL); // from tmp_string[0] = string[0]; tmp_string[1] = string[1]; tmp_string[2] = '\0'; from = square_from_string(tmp_string); if (from == SquareNone) return MoveNone; // to tmp_string[0] = string[2]; tmp_string[1] = string[3]; tmp_string[2] = '\0'; to = square_from_string(tmp_string); if (to == SquareNone) return MoveNone; move = MOVE_MAKE(from,to); // promote switch (string[4]) { case '\0': // not a promotion break; case 'n': move |= MovePromoteKnight; break; case 'b': move |= MovePromoteBishop; break; case 'r': move |= MovePromoteRook; break; case 'q': move |= MovePromoteQueen; break; default: return MoveNone; } // flags piece = board->square[from]; if (PIECE_IS_PAWN(piece)) { if (to == board->ep_square) move |= MoveEnPassant; } else if (PIECE_IS_KING(piece)) { delta = to - from; if (delta == +2 || delta == -2) move |= MoveCastle; } return move; } // end of move.cpp toga2-3.0.0.1SE1/src/LICENSE0000644000175000017500000000164111125217322014352 0ustar oliveroliverThis is taken from http://www.superchessengine.com/toga_ii.htm ============================================================================== Toga II 1.3x4 (beta version) based on Fruit 2.1 by Fabien Letouzey. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See the file "copying.txt" for details. toga2-3.0.0.1SE1/src/material.cpp0000644000175000017500000004531412120151202015642 0ustar oliveroliver // material.cpp // includes #include #include "board.h" #include "colour.h" #include "hash.h" #include "material.h" #include "option.h" #include "piece.h" #include "protocol.h" #include "square.h" #include "util.h" #include "search.h" // constants static const bool UseTable = true; static const uint32 TableSize = 256; // was 256 4kB tried 16384 static const int PawnPhase = 0; static const int KnightPhase = 1; static const int BishopPhase = 1; static const int RookPhase = 2; static const int QueenPhase = 4; static const int TotalPhase = PawnPhase * 16 + KnightPhase * 4 + BishopPhase * 4 + RookPhase * 4 + QueenPhase * 2; // constants and variables #define ABS(x) ((x)<0?-(x):(x)) static /* const */ int OpeningExchangePenalty = 30; /* Thomas penalty exchange piece pawn */ static /* const */ int EndgameExchangePenalty = 30; static /* const */ int MaterialWeight = 256; // 100% static const int PawnOpening = 75; /// J Donald's settings, was 80, 100, 70 static const int PawnEndgame = 90; // was 100 static const int KnightOpening = 325; static const int KnightEndgame = 310; // J Donald's settings, was 315 static const int BishopOpening = 325; static const int BishopEndgame = 320; // Chris Formula's setting was 315 static const int RookOpening = 490; // J Donald's settings, was 500 static const int RookEndgame = 510; // J Donald's settings, was 500 static const int QueenOpening = 975; // was 1000 static const int QueenEndgame = 1000; static const int BishopPairOpening = 45; // JD setting; was 50 static const int BishopPairEndgame = 65; // JD setting; was 50 static /* const */ int KingPawnBonus = 30; // Endgame material adjustments static /* const */ int RookPawnPenalty = 10; // types typedef material_info_t entry_t; struct material_t { entry_t * table; uint32 size; uint32 mask; uint32 used; sint64 read_nb; sint64 read_hit; sint64 write_nb; sint64 write_collision; }; // variables static material_t Material[MaxThreads][1]; // prototypes static void material_comp_info (material_info_t * info, const board_t * board); // functions // material_init() void material_parameter() { // UCI options MaterialWeight = (option_get_int("Material") * 256 + 50) / 100; OpeningExchangePenalty = option_get_int("Toga Exchange Bonus"); EndgameExchangePenalty = OpeningExchangePenalty; // Endgame settings KingPawnBonus = option_get_int("Toga King Pawn Endgame Bonus"); RookPawnPenalty = option_get_int("Toga Rook Pawn Endgame Penalty"); } void material_init() { int ThreadId; // UCI options material_parameter(); // material table for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ Material[ThreadId]->size = 0; Material[ThreadId]->mask = 0; Material[ThreadId]->table = NULL; } } // material_alloc() void material_alloc() { int ThreadId; ASSERT(sizeof(entry_t)==16); if (UseTable) { for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ Material[ThreadId]->size = TableSize; Material[ThreadId]->mask = TableSize - 1; Material[ThreadId]->table = (entry_t *) my_malloc(Material[ThreadId]->size*sizeof(entry_t)); material_clear(ThreadId); } } } // material_free() void material_free() { int ThreadId; ASSERT(sizeof(entry_t)==16); if (UseTable) { for (ThreadId = 0; ThreadId < NumberThreads; ThreadId++){ my_free(Material[ThreadId]->table); } } } // material_clear() void material_clear(int ThreadId) { if (Material[ThreadId]->table != NULL) { memset(Material[ThreadId]->table,0,Material[ThreadId]->size*sizeof(entry_t)); } Material[ThreadId]->used = 0; Material[ThreadId]->read_nb = 0; Material[ThreadId]->read_hit = 0; Material[ThreadId]->write_nb = 0; Material[ThreadId]->write_collision = 0; } // material_get_info() void material_get_info(material_info_t * info, const board_t * board, int ThreadId) { uint64 key; entry_t * entry; ASSERT(info!=NULL); ASSERT(board!=NULL); // probe if (UseTable) { Material[ThreadId]->read_nb++; key = board->material_key; entry = &Material[ThreadId]->table[KEY_INDEX(key)&Material[ThreadId]->mask]; if (entry->lock == KEY_LOCK(key)) { // found Material[ThreadId]->read_hit++; *info = *entry; return; } } // calculation material_comp_info(info,board); // store if (UseTable) { Material[ThreadId]->write_nb++; if (entry->lock == 0) { // HACK: assume free entry Material[ThreadId]->used++; } else { Material[ThreadId]->write_collision++; } *entry = *info; entry->lock = KEY_LOCK(key); } } // material_comp_info() static void material_comp_info(material_info_t * info, const board_t * board) { int wp, wn, wb, wr, wq; int bp, bn, bb, br, bq; int wt, bt; int wm, bm; int colour; int recog; int flags; int cflags[ColourNb]; int mul[ColourNb]; int phase; int opening, endgame; int owf,obf,ewf,ebf; /* Thomas */ int WhiteMinors,BlackMinors,WhiteMajors,BlackMajors; ASSERT(info!=NULL); ASSERT(board!=NULL); // init wp = board->number[WhitePawn12]; wn = board->number[WhiteKnight12]; wb = board->number[WhiteBishop12]; wr = board->number[WhiteRook12]; wq = board->number[WhiteQueen12]; bp = board->number[BlackPawn12]; bn = board->number[BlackKnight12]; bb = board->number[BlackBishop12]; br = board->number[BlackRook12]; bq = board->number[BlackQueen12]; wt = wq + wr + wb + wn + wp; // no king bt = bq + br + bb + bn + bp; // no king wm = wb + wn; bm = bb + bn; // recogniser recog = MAT_NONE; if (false) { } else if (wt == 0 && bt == 0) { recog = MAT_KK; } else if (wt == 1 && bt == 0) { if (wb == 1) recog = MAT_KBK; if (wn == 1) recog = MAT_KNK; if (wp == 1) recog = MAT_KPK; } else if (wt == 0 && bt == 1) { if (bb == 1) recog = MAT_KKB; if (bn == 1) recog = MAT_KKN; if (bp == 1) recog = MAT_KKP; } else if (wt == 1 && bt == 1) { if (wq == 1 && bq == 1) recog = MAT_KQKQ; if (wq == 1 && bp == 1) recog = MAT_KQKP; if (wp == 1 && bq == 1) recog = MAT_KPKQ; if (wr == 1 && br == 1) recog = MAT_KRKR; if (wr == 1 && bp == 1) recog = MAT_KRKP; if (wp == 1 && br == 1) recog = MAT_KPKR; if (wb == 1 && bb == 1) recog = MAT_KBKB; if (wb == 1 && bp == 1) recog = MAT_KBKP; if (wp == 1 && bb == 1) recog = MAT_KPKB; if (wn == 1 && bn == 1) recog = MAT_KNKN; if (wn == 1 && bp == 1) recog = MAT_KNKP; if (wp == 1 && bn == 1) recog = MAT_KPKN; } else if (wt == 2 && bt == 0) { if (wb == 1 && wp == 1) recog = MAT_KBPK; if (wn == 1 && wp == 1) recog = MAT_KNPK; } else if (wt == 0 && bt == 2) { if (bb == 1 && bp == 1) recog = MAT_KKBP; if (bn == 1 && bp == 1) recog = MAT_KKNP; } else if (wt == 2 && bt == 1) { if (wr == 1 && wp == 1 && br == 1) recog = MAT_KRPKR; if (wb == 1 && wp == 1 && bb == 1) recog = MAT_KBPKB; } else if (wt == 1 && bt == 2) { if (wr == 1 && br == 1 && bp == 1) recog = MAT_KRKRP; if (wb == 1 && bb == 1 && bp == 1) recog = MAT_KBKBP; } // draw node (exact-draw recogniser) flags = 0; // TODO: MOVE ME for (colour = 0; colour < ColourNb; colour++) cflags[colour] = 0; if (wq+wr+wp == 0 && bq+br+bp == 0) { // no major piece or pawn if (wm + bm <= 1 // at most one minor => KK, KBK or KNK || recog == MAT_KBKB) { flags |= DrawNodeFlag; } } else if (recog == MAT_KPK || recog == MAT_KKP || recog == MAT_KBPK || recog == MAT_KKBP) { flags |= DrawNodeFlag; } // bishop endgame if (wq+wr+wn == 0 && bq+br+bn == 0) { // only bishops if (wb == 1 && bb == 1) { if (wp-bp >= -2 && wp-bp <= +2) { // pawn diff <= 2 flags |= DrawBishopFlag; } } } // multipliers for (colour = 0; colour < ColourNb; colour++) mul[colour] = 16; // 1 // white multiplier if (wp == 0) { // white has no pawns int w_maj = wq * 2 + wr; int w_min = wb + wn; int w_tot = w_maj * 2 + w_min; int b_maj = bq * 2 + br; int b_min = bb + bn; int b_tot = b_maj * 2 + b_min; if (false) { } else if (w_tot == 1) { ASSERT(w_maj==0); ASSERT(w_min==1); // KBK* or KNK*, always insufficient mul[White] = 0; } else if (w_tot == 2 && wn == 2) { ASSERT(w_maj==0); ASSERT(w_min==2); // KNNK*, usually insufficient if (b_tot != 0 || bp == 0) { mul[White] = 0; } else { // KNNKP+, might not be draw mul[White] = 1; // 1/16 } } else if (w_tot == 2 && wb == 2 && b_tot == 1 && bn == 1) { ASSERT(w_maj==0); ASSERT(w_min==2); ASSERT(b_maj==0); ASSERT(b_min==1); // KBBKN*, barely drawish (not at all?) mul[White] = 8; // 1/2 } else if (w_tot-b_tot <= 1 && w_maj <= 2) { // no more than 1 minor up, drawish mul[White] = 2; // 1/8 } } else if (wp == 1) { // white has one pawn int w_maj = wq * 2 + wr; int w_min = wb + wn; int w_tot = w_maj * 2 + w_min; int b_maj = bq * 2 + br; int b_min = bb + bn; int b_tot = b_maj * 2 + b_min; if (false) { } else if (b_min != 0) { // assume black sacrifices a minor against the lone pawn b_min--; b_tot--; if (false) { } else if (w_tot == 1) { ASSERT(w_maj==0); ASSERT(w_min==1); // KBK* or KNK*, always insufficient mul[White] = 4; // 1/4 } else if (w_tot == 2 && wn == 2) { ASSERT(w_maj==0); ASSERT(w_min==2); // KNNK*, usually insufficient mul[White] = 4; // 1/4 } else if (w_tot-b_tot <= 1 && w_maj <= 2) { // no more than 1 minor up, drawish mul[White] = 8; // 1/2 } } else if (br != 0) { // assume black sacrifices a rook against the lone pawn b_maj--; b_tot -= 2; if (false) { } else if (w_tot == 1) { ASSERT(w_maj==0); ASSERT(w_min==1); // KBK* or KNK*, always insufficient mul[White] = 4; // 1/4 } else if (w_tot == 2 && wn == 2) { ASSERT(w_maj==0); ASSERT(w_min==2); // KNNK*, usually insufficient mul[White] = 4; // 1/4 } else if (w_tot-b_tot <= 1 && w_maj <= 2) { // no more than 1 minor up, drawish mul[White] = 8; // 1/2 } } } // black multiplier if (bp == 0) { // black has no pawns int w_maj = wq * 2 + wr; int w_min = wb + wn; int w_tot = w_maj * 2 + w_min; int b_maj = bq * 2 + br; int b_min = bb + bn; int b_tot = b_maj * 2 + b_min; if (false) { } else if (b_tot == 1) { ASSERT(b_maj==0); ASSERT(b_min==1); // KBK* or KNK*, always insufficient mul[Black] = 0; } else if (b_tot == 2 && bn == 2) { ASSERT(b_maj==0); ASSERT(b_min==2); // KNNK*, usually insufficient if (w_tot != 0 || wp == 0) { mul[Black] = 0; } else { // KNNKP+, might not be draw mul[Black] = 1; // 1/16 } } else if (b_tot == 2 && bb == 2 && w_tot == 1 && wn == 1) { ASSERT(b_maj==0); ASSERT(b_min==2); ASSERT(w_maj==0); ASSERT(w_min==1); // KBBKN*, barely drawish (not at all?) mul[Black] = 8; // 1/2 } else if (b_tot-w_tot <= 1 && b_maj <= 2) { // no more than 1 minor up, drawish mul[Black] = 2; // 1/8 } } else if (bp == 1) { // black has one pawn int w_maj = wq * 2 + wr; int w_min = wb + wn; int w_tot = w_maj * 2 + w_min; int b_maj = bq * 2 + br; int b_min = bb + bn; int b_tot = b_maj * 2 + b_min; if (false) { } else if (w_min != 0) { // assume white sacrifices a minor against the lone pawn w_min--; w_tot--; if (false) { } else if (b_tot == 1) { ASSERT(b_maj==0); ASSERT(b_min==1); // KBK* or KNK*, always insufficient mul[Black] = 4; // 1/4 } else if (b_tot == 2 && bn == 2) { ASSERT(b_maj==0); ASSERT(b_min==2); // KNNK*, usually insufficient mul[Black] = 4; // 1/4 } else if (b_tot-w_tot <= 1 && b_maj <= 2) { // no more than 1 minor up, drawish mul[Black] = 8; // 1/2 } } else if (wr != 0) { // assume white sacrifices a rook against the lone pawn w_maj--; w_tot -= 2; if (false) { } else if (b_tot == 1) { ASSERT(b_maj==0); ASSERT(b_min==1); // KBK* or KNK*, always insufficient mul[Black] = 4; // 1/4 } else if (b_tot == 2 && bn == 2) { ASSERT(b_maj==0); ASSERT(b_min==2); // KNNK*, usually insufficient mul[Black] = 4; // 1/4 } else if (b_tot-w_tot <= 1 && b_maj <= 2) { // no more than 1 minor up, drawish mul[Black] = 8; // 1/2 } } } // potential draw for white if (wt == wb+wp && wp >= 1) cflags[White] |= MatRookPawnFlag; if (wt == wb+wp && wb <= 1 && wp >= 1 && bt > bp) cflags[White] |= MatBishopFlag; if (wt == 2 && wn == 1 && wp == 1 && bt > bp) cflags[White] |= MatKnightFlag; // potential draw for black if (bt == bb+bp && bp >= 1) cflags[Black] |= MatRookPawnFlag; if (bt == bb+bp && bb <= 1 && bp >= 1 && wt > wp) cflags[Black] |= MatBishopFlag; if (bt == 2 && bn == 1 && bp == 1 && wt > wp) cflags[Black] |= MatKnightFlag; // draw leaf (likely draw) if (recog == MAT_KQKQ || recog == MAT_KRKR) { mul[White] = 0; mul[Black] = 0; } // king safety if (bq >= 1 && bq+br+bb+bn >= 2) cflags[White] |= MatKingFlag; if (wq >= 1 && wq+wr+wb+wn >= 2) cflags[Black] |= MatKingFlag; // phase (0: opening -> 256: endgame) phase = TotalPhase; phase -= wp * PawnPhase; phase -= wn * KnightPhase; phase -= wb * BishopPhase; phase -= wr * RookPhase; phase -= wq * QueenPhase; phase -= bp * PawnPhase; phase -= bn * KnightPhase; phase -= bb * BishopPhase; phase -= br * RookPhase; phase -= bq * QueenPhase; if (phase < 0) phase = 0; ASSERT(phase>=0&&phase<=TotalPhase); phase = (phase * 256 + (TotalPhase / 2)) / TotalPhase; ASSERT(phase>=0&&phase<=256); // material opening = 0; endgame = 0; /* Thomas */ owf = wn*KnightOpening + wb*BishopOpening + wr*RookOpening + wq*QueenOpening; opening += owf; opening += wp * PawnOpening; obf = bn*KnightOpening + bb*BishopOpening + br*RookOpening + bq*QueenOpening; opening -= obf; opening -= bp * PawnOpening; ewf = wn*KnightEndgame + wb*BishopEndgame + wr*RookEndgame + wq*QueenEndgame; endgame += wp * PawnEndgame; endgame += ewf; ebf = bn*KnightEndgame + bb*BishopEndgame + br*RookEndgame + bq*QueenEndgame; endgame -= bp * PawnEndgame; endgame -= ebf; /* WhiteMinors = wn + wb; BlackMinors = bn + bb; WhiteMajors = 2*wq + wr; BlackMajors = 2*bq + br; */ // Trade Bonus if (owf > obf && bp > wp){ opening += OpeningExchangePenalty; endgame += OpeningExchangePenalty; } else if (obf > owf && wp > bp){ opening -= OpeningExchangePenalty; endgame -= OpeningExchangePenalty; } /* if (WhiteMinors != BlackMinors) { if (WhiteMajors == BlackMajors) { if (WhiteMinors > BlackMinors){ opening += OpeningExchangePenalty; endgame += OpeningExchangePenalty; } else{ opening -= OpeningExchangePenalty; endgame -= OpeningExchangePenalty; } } } */ // Adjust knight and rook material values // White /* opening += wr * (5 - wp) * PawnOpening/8; endgame += wr * (5 - wp) * PawnEndgame/8; opening += wn * (wp - 5) * PawnOpening/16; endgame += wn * (wp - 5) * PawnEndgame/16; // Black opening -= br * (5 - bp) * PawnOpening/8; endgame -= br * (5 - bp) * PawnEndgame/8; opening -= bn * (bp - 5) * PawnOpening/16; endgame -= bn * (bp - 5) * PawnEndgame/16; */ // bishop pair if (wb >= 2) { // HACK: assumes different colours opening += BishopPairOpening; endgame += BishopPairEndgame; } if (bb >= 2) { // HACK: assumes different colours opening -= BishopPairOpening; endgame -= BishopPairEndgame; } // JD: King and Pawn Endgames (usually winning) if (wt - wp == 0 && bt - bp == 0){ // TODO adjust by (wp-bp)*constant if (wp > bp+1){ endgame += KingPawnBonus*2; } else if (wp > bp){ endgame += KingPawnBonus; } if (bp > wp+1){ endgame -= KingPawnBonus*2; } else if (bp > wp){ endgame -= KingPawnBonus; } } // Rook and Pawn Endgames (drawish) if (wt - wp == 1 && bt - bp == 1 && wr == 1 && br == 1){ if (wp > bp){ endgame -= RookPawnPenalty; // note - sign } if (bp > wp){ endgame += RookPawnPenalty; } } // Piece combo: Queen + Knight against Queen + Bishop if (wt-wp == 2 && bt-wp == 2 && wq == 1 && bq == 1 && wn == 1 && bb == 1) endgame += 10; else if (wt-wp == 2 && bt-wp == 2 && wq == 1 && bq == 1 && wb == 1 && bn == 1) endgame -= 10; // store info info->recog = recog; info->flags = flags; for (colour = 0; colour < ColourNb; colour++) info->cflags[colour] = cflags[colour]; for (colour = 0; colour < ColourNb; colour++) info->mul[colour] = mul[colour]; info->phase = phase; info->opening = (opening * MaterialWeight) / 256; info->endgame = (endgame * MaterialWeight) / 256; } // end of material.cpp toga2-3.0.0.1SE1/src/trans.h0000644000175000017500000000270311125217320014643 0ustar oliveroliver // trans.h #ifndef TRANS_H #define TRANS_H // includes #include "util.h" // constants const int TransUpperFlag = 1 << 0; const int TransLowerFlag = 1 << 1; const int TransUnknown = 0; const int TransUpper = TransUpperFlag; const int TransLower = TransLowerFlag; const int TransExact = TransUpperFlag | TransLowerFlag; const int TransFlags = 3; // macros #define TRANS_IS_UPPER(flags) (((flags)&TransUpperFlag)!=0) #define TRANS_IS_LOWER(flags) (((flags)&TransLowerFlag)!=0) #define TRANS_IS_EXACT(flags) ((flags)==TransExact) struct entry_t { uint64 key; uint16 move; uint8 depth; uint8 date_flags; sint16 value; uint16 nproc; }; // types typedef struct trans trans_t; // variables extern trans_t Trans[1]; extern bool trans_endgame; // functions extern bool trans_is_ok (const trans_t * trans); extern void trans_init (trans_t * trans); extern void trans_alloc (trans_t * trans); extern void trans_free (trans_t * trans); extern void trans_clear (trans_t * trans); extern void trans_inc_date (trans_t * trans); extern void trans_store (trans_t * trans, uint64 key, int move, int depth, int flags, int value); extern bool trans_retrieve (trans_t * trans, entry_t ** found_entry, uint64 key, int * move, int * depth, int * flags, int * value); extern void trans_stats (const trans_t * trans); #endif // !defined TRANS_H // end of trans.h toga2-3.0.0.1SE1/src/eval.cpp0000644000175000017500000016046212120151204014777 0ustar oliveroliver // eval.cpp // includes #include // for abs() #include "attack.h" #include "board.h" #include "colour.h" #include "eval.h" #include "material.h" #include "move.h" #include "option.h" #include "pawn.h" #include "piece.h" #include "see.h" #include "util.h" #include "value.h" #include "vector.h" //#include "probe.h" #include "search.h" // macros #define THROUGH(piece) ((piece)==Empty) #define ABS(x) ((x)<0?-(x):(x)) // constants and variables const int KnightOutpostMatrix[2][64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 10, 10, 5 , 2, 0, 0, 2, 5, 10, 10, 5, 2, 0, 0, 0, 4, 5, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 4, 0, 0, 0, 2, 5, 10, 10, 5, 2, 0, 0, 2, 5, 10, 10, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static int lazy_eval_cutoff = 200; /* Thomas */ static int second_lazy_eval_cutoff = 125; /* JD */ static bool LazyEval = false; // true //static bool KingSafety = false; // true //static int KingSafetyMargin = 1600; //static bool king_is_safe[ColourNb]; static /* const */ int PieceActivityWeight = 256; // 100% static /* const */ int KingSafetyWeight = 256; // 100% static /* const */ int PassedPawnWeight = 256; // 100% static const int KnightUnit = 4; static const int BishopUnit = 4; // only forwards static const int RookUnit = 7; //static const int QueenUnit = 13; static const int MobMove = 1; static const int MobAttack = 1; static const int MobDefense = 0; static const int MobPieceDefense = 1; static const int KnightMobOpening = 4; static const int KnightMobEndgame = 4; static const int BishopMobOpening = 5; static const int BishopMobEndgame = 5; static const int RookMobOpening = 2; static const int RookMobEndgame = 4; //static const int QueenMobOpening = 1; //static const int QueenMobEndgame = 2; //static const int KingMobOpening = 0; //static const int KingMobEndgame = 0; // Ryan's speedup of eval_piece(). Posted open source in GambitFruit. // Bishop mobility modified by Jerry Donald static const int knight_mob_opening[8 + 1] = {-16, -12, -8, -4, 0, 4, 8, 12, 16}; // WHM; slope == KinghtMobOpening == 4 static const int knight_mob_endgame[8 + 1] = {-16, -12, -8, -4, 0, 4, 8, 12, 16}; // WHM; slope == KinghtMobEndgame == 4 static const int bishop_mob_opening[8 + 1] = {-20, -15, -10, -5, 0, 5, 10, 15, 20}; // WHM; slope == BishopMobOpening == 5 static const int bishop_mob_endgame[8 + 1] = {-20, -15, -10, -5, 0, 5, 10, 15, 20}; // WHM; slope == BishopMobEndgame == 5 static const int rook_mob_opening[14 + 1] = {-14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14}; // WHM; slope == RookMobOpening == 2 static const int rook_mob_endgame[14 + 1] = {-28, -24, -20, -16, -12, -8, -4, 0, 4, 8, 12, 16, 20, 24, 28}; // WHM; slope == RookMobEndgame == 4 static const bool UseOpenFile = true; static const int RookSemiOpenFileOpening = 10; static const int RookSemiOpenFileEndgame = 10; static const int RookOpenFileOpening = 20; static const int RookOpenFileEndgame = 20; static const int RookSemiKingFileOpening = 10; static const int RookKingFileOpening = 20; static const bool UseKingAttack = true; static const int KingAttackOpening = 20; // was 20 static const int KingAttackOpening1 = 20; // was 20 static const bool UseShelter = true; static const int ShelterOpening = 256; // 100% static const bool UseStorm = true; static const int StormOpening = 10; static const int Rook7thOpening = 20; static const int Rook7thEndgame = 40; static const int Queen7thOpening = 10; static const int Queen7thEndgame = 20; static const int TrappedBishop = 100; static const int BlockedBishop = 50; static const int BlockedRook = 50; static const int ProtectedPassedOpening = 10; static const int ProtectedPassedEndgame = 20; static const int PassedOpeningMin = 10; static const int PassedOpeningMax = 70; static const int PassedEndgameMin = 20; static const int PassedEndgameMax = 140; static const int UnstoppablePasser = 800; static const int FreePasser = 60; static const int AttackerDistance = 5; static const int DefenderDistance = 20; // "constants" // pawn shelter penalties static const int PawnShelterFront[7] = { 72, 70, 64, 54, 40, 22, 0, // rank 8 (or no pawn) to rank 2 (0 penalty) }; static const int PawnShelterOpenSide[7] = { 36, 35, 32, 26, 18, 14, 0, }; static const int PawnShelterClosedSide[7] = { 36, 35, 32, 27, 19, 9, 0, }; // weights static const int KingAttackWeight[16] = { 0, 0, 128, 192, 224, 240, 248, 252, 254, 255, 256, 256 ,256, 256, 256, 256, }; /*static const int SSpaceWeight[16] = { 0, 0, 10, 40, 70, 90, 90, 90, 90, 90, 90, 90 ,90, 90, 90, 90, };*/ static const int SSpaceWeight[16] = { 0, 2, 5, 8, 12, 15, 20, 20, 20, 20, 20, 20 ,20, 20, 20, 20, }; // types static const int TypeShelterFront = 1; static const int TypeShelterOpen = 0; static const int TypeShelterClosed = -1; // variables static int MobUnit[ColourNb][PieceNb]; static int KingAttackUnit[PieceNb]; // prototypes static void eval_draw (const board_t * board, const material_info_t * mat_info, const pawn_info_t * pawn_info, int mul[2]); static void eval_piece (const board_t * board, const material_info_t * mat_info, const pawn_info_t * pawn_info, int * opening, int * endgame); static void eval_king (const board_t * board, const material_info_t * mat_info, int * opening, int * endgame); static void eval_passer (const board_t * board, const pawn_info_t * pawn_info, int * opening, int * endgame); static void eval_pattern (const board_t * board, int * opening, int * endgame); static bool unstoppable_passer (const board_t * board, int pawn, int colour); static bool king_passer (const board_t * board, int pawn, int colour); static bool free_passer (const board_t * board, int pawn, int colour); static int pawn_att_dist (int pawn, int king, int colour); static int pawn_def_dist (int pawn, int king, int colour); static void draw_init_list (int list[], const board_t * board, int pawn_colour); static bool draw_kpkq (const int list[], int turn); static bool draw_kpkr (const int list[], int turn); static bool draw_kpkb (const int list[], int turn); static bool draw_kpkn (const int list[], int turn); static bool draw_knpk (const int list[], int turn); static bool draw_krpkr (const int list[], int turn); static bool draw_kbpkb (const int list[], int turn); static int shelter_square (const board_t * board, const material_info_t * mat_info, int square, int colour); static int shelter_file (const board_t * board, int file, int rank, int colour, int type); static int storm_file (const board_t * board, int file, int colour); static bool bishop_can_attack (const board_t * board, int to, int colour); // functions void eval_parameter() { // UCI options PieceActivityWeight = (option_get_int("Piece Activity") * 256 + 50) / 100; KingSafetyWeight = (option_get_int("King Safety") * 256 + 50) / 100; PassedPawnWeight = (option_get_int("Passed Pawns") * 256 + 50) / 100; LazyEval = option_get_bool("Toga Lazy Eval"); /* Thomas */ lazy_eval_cutoff = option_get_int("Toga Lazy Eval Margin"); second_lazy_eval_cutoff = option_get_int("Toga Lazy Eval Mobility Margin"); //KingSafetyMargin = option_get_int("Toga King Safety Margin"); //KingSafety = option_get_bool("Toga King Safety"); } // eval_init() void eval_init() { int colour; int piece; // UCI options eval_parameter(); // mobility table for (colour = 0; colour < ColourNb; colour++) { for (piece = 0; piece < PieceNb; piece++) { MobUnit[colour][piece] = 0; } } MobUnit[White][Empty] = MobMove; MobUnit[White][BP] = MobAttack; MobUnit[White][BN] = MobAttack; MobUnit[White][BB] = MobAttack; MobUnit[White][BR] = MobAttack; MobUnit[White][BQ] = MobAttack; MobUnit[White][BK] = MobAttack; MobUnit[White][WP] = MobDefense; MobUnit[White][WN] = MobPieceDefense; MobUnit[White][WB] = MobPieceDefense; MobUnit[White][WR] = MobPieceDefense; MobUnit[White][WQ] = MobPieceDefense; MobUnit[White][WK] = MobDefense; MobUnit[Black][Empty] = MobMove; MobUnit[Black][WP] = MobAttack; MobUnit[Black][WN] = MobAttack; MobUnit[Black][WB] = MobAttack; MobUnit[Black][WR] = MobAttack; MobUnit[Black][WQ] = MobAttack; MobUnit[Black][WK] = MobAttack; MobUnit[Black][BP] = MobDefense; MobUnit[Black][BN] = MobPieceDefense; MobUnit[Black][BB] = MobPieceDefense; MobUnit[Black][BR] = MobPieceDefense; MobUnit[Black][BQ] = MobPieceDefense; MobUnit[Black][BK] = MobDefense; // KingAttackUnit[] for (piece = 0; piece < PieceNb; piece++) { KingAttackUnit[piece] = 0; } KingAttackUnit[WN] = 1; KingAttackUnit[WB] = 1; KingAttackUnit[WR] = 2; KingAttackUnit[WQ] = 4; KingAttackUnit[BN] = 1; KingAttackUnit[BB] = 1; KingAttackUnit[BR] = 2; KingAttackUnit[BQ] = 4; } // eval() int eval(board_t * board, int alpha, int beta, int ThreadId) { int opening, endgame; material_info_t mat_info[1]; pawn_info_t pawn_info[1]; int mul[ColourNb]; int phase; int eval; int wb, bb; int lazy_eval,probe_score; // Thomas ASSERT(board!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); // fixed by adding in_check condition to razoring (JD) // init opening = 0; endgame = 0; /* if (egbb_is_loaded && board->piece_nb <=5 && ABS(SearchBest[0].value) >= WIN_SCORE) { if (probe_bitbases(board, probe_score)){ return probe_score; } } */ // material material_get_info(mat_info,board,ThreadId); phase = mat_info->phase; opening += mat_info->opening; endgame += mat_info->endgame; mul[White] = mat_info->mul[White]; mul[Black] = mat_info->mul[Black]; // PST opening += board->opening; endgame += board->endgame; // pawns pawn_get_info(pawn_info,board,ThreadId); opening += pawn_info->opening; endgame += pawn_info->endgame; // draw eval_draw(board,mat_info,pawn_info,mul); if (mat_info->mul[White] < mul[White]) mul[White] = mat_info->mul[White]; if (mat_info->mul[Black] < mul[Black]) mul[Black] = mat_info->mul[Black]; if (mul[White] == 0 && mul[Black] == 0) return ValueDraw; // eval // Tempo if (COLOUR_IS_WHITE(board->turn)){ opening += 20; endgame += 10; } else{ opening -= 20; endgame -= 10; } eval_pattern(board,&opening,&endgame); // Lazy Eval (Thomas) // returns material+pst+pattern+pawn structure if (LazyEval && board->piece_size[White] > 3 && board->piece_size[Black] > 3){ lazy_eval = ((opening * (256 - phase)) + (endgame * phase)) / 256; ASSERT(eval>=-ValueEvalInf&&eval<=+ValueEvalInf); if (COLOUR_IS_BLACK(board->turn)) lazy_eval = -lazy_eval; if (lazy_eval - lazy_eval_cutoff >= beta) return (lazy_eval); if (lazy_eval + lazy_eval_cutoff <= alpha) return (lazy_eval); } // eval eval_king(board,mat_info,&opening,&endgame); eval_passer(board,pawn_info,&opening,&endgame); // 2nd Lazy Eval Cutoff JD // ~10% speedup, reasonably safe // returns without computing expensive mobility if (LazyEval && board->piece_size[White] > 3 && board->piece_size[Black] > 3){ // TODO try without 2nd & 3rd conditions lazy_eval = ((opening * (256 - phase)) + (endgame * phase)) / 256; ASSERT(eval>=-ValueEvalInf&&eval<=+ValueEvalInf); if (COLOUR_IS_BLACK(board->turn)) lazy_eval = -lazy_eval; if (lazy_eval - second_lazy_eval_cutoff >= beta) return (lazy_eval); if (lazy_eval + second_lazy_eval_cutoff <= alpha) return (lazy_eval); // end lazy cuttoff } eval_piece(board,mat_info,pawn_info,&opening,&endgame); // eval_pattern(board,&opening,&endgame); /*if (board->piece_nb == 4){ if (board->number[WhiteKnight12] + board->number[WhiteBishop12] == 2){ eval = 0; wb = board->piece[White][1]; if (SQUARE_COLOUR(wb) == SQUARE_COLOUR(A8)){ wb = MIN(DISTANCE(A8,KING_POS(board,Black)),DISTANCE(H1,KING_POS(board,Black))); eval += 140 - wb * 20; wb = DISTANCE(KING_POS(board,White),KING_POS(board,Black)); eval += 360 - wb * 40; } else{ wb = MIN(DISTANCE(A1,KING_POS(board,Black)),DISTANCE(H8,KING_POS(board,Black))); eval += 140 - wb * 20; wb = DISTANCE(KING_POS(board,White),KING_POS(board,Black)); eval += 360 - wb * 40; } } else if (board->number[BlackKnight12] + board->number[BlackBishop12] == 2){ eval = 0; wb = board->piece[Black][1]; if (SQUARE_COLOUR(wb) == SQUARE_COLOUR(A8)){ wb = MIN(DISTANCE(A8,KING_POS(board,White)),DISTANCE(H1,KING_POS(board,White))); eval -= 140 - wb * 20; wb = DISTANCE(KING_POS(board,White),KING_POS(board,Black)); eval -= 360 - wb * 40; } else{ wb = MIN(DISTANCE(A1,KING_POS(board,White)),DISTANCE(H8,KING_POS(board,White))); eval -= 140 - wb * 20; wb = DISTANCE(KING_POS(board,White),KING_POS(board,Black)); eval -= 360 - wb * 40; } } } */ // phase mix eval = ((opening * (256 - phase)) + (endgame * phase)) / 256; // drawish bishop endgames if ((mat_info->flags & DrawBishopFlag) != 0) { wb = board->piece[White][1]; ASSERT(PIECE_IS_BISHOP(board->square[wb])); bb = board->piece[Black][1]; ASSERT(PIECE_IS_BISHOP(board->square[bb])); if (SQUARE_COLOUR(wb) != SQUARE_COLOUR(bb)) { if (mul[White] == 16) mul[White] = 8; // 1/2 if (mul[Black] == 16) mul[Black] = 8; // 1/2 } } // draw bound if (eval > ValueDraw) { eval = (eval * mul[White]) / 16; } else if (eval < ValueDraw) { eval = (eval * mul[Black]) / 16; } // value range if (eval < -ValueEvalInf) eval = -ValueEvalInf; if (eval > +ValueEvalInf) eval = +ValueEvalInf; ASSERT(eval>=-ValueEvalInf&&eval<=+ValueEvalInf); // turn if (COLOUR_IS_BLACK(board->turn)) eval = -eval; ASSERT(!value_is_mate(eval)); return eval; } // eval_draw() static void eval_draw(const board_t * board, const material_info_t * mat_info, const pawn_info_t * pawn_info, int mul[2]) { int colour; int me, opp; int pawn, king; int pawn_file; int prom; int list[7+1]; ASSERT(board!=NULL); ASSERT(mat_info!=NULL); ASSERT(pawn_info!=NULL); ASSERT(mul!=NULL); // draw patterns for (colour = 0; colour < ColourNb; colour++) { me = colour; opp = COLOUR_OPP(me); // KB*P+K* draw if ((mat_info->cflags[me] & MatRookPawnFlag) != 0) { pawn = pawn_info->single_file[me]; if (pawn != SquareNone) { // all pawns on one file pawn_file = SQUARE_FILE(pawn); if (pawn_file == FileA || pawn_file == FileH) { king = KING_POS(board,opp); prom = PAWN_PROMOTE(pawn,me); if (DISTANCE(king,prom) <= 1 && !bishop_can_attack(board,prom,me)) { mul[me] = 0; } } } } // K(B)P+K+ draw if ((mat_info->cflags[me] & MatBishopFlag) != 0) { pawn = pawn_info->single_file[me]; if (pawn != SquareNone) { // all pawns on one file king = KING_POS(board,opp); if (SQUARE_FILE(king) == SQUARE_FILE(pawn) && PAWN_RANK(king,me) > PAWN_RANK(pawn,me) && !bishop_can_attack(board,king,me)) { mul[me] = 1; // 1/16 } } } // KNPK* draw if ((mat_info->cflags[me] & MatKnightFlag) != 0) { pawn = board->pawn[me][0]; king = KING_POS(board,opp); if (SQUARE_FILE(king) == SQUARE_FILE(pawn) && PAWN_RANK(king,me) > PAWN_RANK(pawn,me) && PAWN_RANK(pawn,me) <= Rank6) { mul[me] = 1; // 1/16 } } } // recognisers, only heuristic draws here! if (false) { } else if (mat_info->recog == MAT_KPKQ) { // KPKQ (white) draw_init_list(list,board,White); if (draw_kpkq(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KQKP) { // KPKQ (black) draw_init_list(list,board,Black); if (draw_kpkq(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KPKR) { // KPKR (white) draw_init_list(list,board,White); if (draw_kpkr(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KRKP) { // KPKR (black) draw_init_list(list,board,Black); if (draw_kpkr(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KPKB) { // KPKB (white) draw_init_list(list,board,White); if (draw_kpkb(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KBKP) { // KPKB (black) draw_init_list(list,board,Black); if (draw_kpkb(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KPKN) { // KPKN (white) draw_init_list(list,board,White); if (draw_kpkn(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KNKP) { // KPKN (black) draw_init_list(list,board,Black); if (draw_kpkn(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KNPK) { // KNPK (white) draw_init_list(list,board,White); if (draw_knpk(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KKNP) { // KNPK (black) draw_init_list(list,board,Black); if (draw_knpk(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KRPKR) { // KRPKR (white) draw_init_list(list,board,White); if (draw_krpkr(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KRKRP) { // KRPKR (black) draw_init_list(list,board,Black); if (draw_krpkr(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KBPKB) { // KBPKB (white) draw_init_list(list,board,White); if (draw_kbpkb(list,board->turn)) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } else if (mat_info->recog == MAT_KBKBP) { // KBPKB (black) draw_init_list(list,board,Black); if (draw_kbpkb(list,COLOUR_OPP(board->turn))) { mul[White] = 1; // 1/16; mul[Black] = 1; // 1/16; } } } // eval_piece() static void eval_piece(const board_t * board, const material_info_t * mat_info, const pawn_info_t * pawn_info, int * opening, int * endgame) { int colour; int op[ColourNb], eg[ColourNb]; int me, opp; int opp_flag; const sq_t * ptr; int from, to; int piece; int mob; int capture; const int * unit; int rook_file, king_file; int king; int delta; int piece_nb, attackvalue; int king_rank,piece_rank,new_mob, piece_file; ASSERT(board!=NULL); ASSERT(mat_info!=NULL); ASSERT(pawn_info!=NULL); ASSERT(opening!=NULL); ASSERT(endgame!=NULL); // init for (colour = 0; colour < ColourNb; colour++) { op[colour] = 0; eg[colour] = 0; } // eval for (colour = 0; colour < ColourNb; colour++) { me = colour; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); unit = MobUnit[me]; piece_nb = 0; attackvalue = 0; // piece loop for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; switch (PIECE_TYPE(piece)) { case Knight64: // mobility mob = 0; if (me == White){ // Safe Mobility - from Toga Returns 1.1 by Ben Tennison // tested JD ~5 elo self play 4000 games if ((board->square[from-18] != BP && board->square[from-16] != BP)) mob += unit[board->square[from-33]]; if ((board->square[from-16] != BP && board->square[from-14] != BP)) mob += unit[board->square[from-31]]; if ((board->square[from- 3] != BP && board->square[from- 1] != BP)) mob += unit[board->square[from-18]]; if ((board->square[from+ 1] != BP && board->square[from+ 3] != BP)) mob += unit[board->square[from-14]]; if ((board->square[from+48] != BP && board->square[from+50] != BP)) mob += unit[board->square[from+33]]; if ((board->square[from+46] != BP && board->square[from+48] != BP)) mob += unit[board->square[from+31]]; if ((board->square[from+33] != BP && board->square[from+35] != BP)) mob += unit[board->square[from+18]]; if ((board->square[from+29] != BP && board->square[from+31] != BP)) mob += unit[board->square[from+14]]; } else { if ((board->square[from-48] != WP && board->square[from-50] != WP)) mob += unit[board->square[from-33]]; if ((board->square[from-46] != WP && board->square[from-48] != WP)) mob += unit[board->square[from-31]]; if ((board->square[from-33] != WP && board->square[from-35] != WP)) mob += unit[board->square[from-18]]; if ((board->square[from-29] != WP && board->square[from-31] != WP)) mob += unit[board->square[from-14]]; if ((board->square[from+18] != WP && board->square[from+16] != WP)) mob += unit[board->square[from+33]]; if ((board->square[from+16] != WP && board->square[from+14] != WP)) mob += unit[board->square[from+31]]; if ((board->square[from+ 3] != WP && board->square[from+ 1] != WP)) mob += unit[board->square[from+18]]; if ((board->square[from- 1] != WP && board->square[from- 3] != WP)) mob += unit[board->square[from+14]]; } op[me] += knight_mob_opening[mob]; eg[me] += knight_mob_endgame[mob]; // outpost mob = 0; if (me == White && (board->square[from+17] != BP && board->square[from+15] != BP)){// not attacked: idea from DLT if (board->square[from-17] == WP) mob += KnightOutpostMatrix[me][SquareTo64[from]]; if (board->square[from-15] == WP) mob += KnightOutpostMatrix[me][SquareTo64[from]]; } else if (me == Black && (board->square[from-17] != WP && board->square[from-15] != WP)){ if (board->square[from+17] == BP) mob += KnightOutpostMatrix[me][SquareTo64[from]]; if (board->square[from+15] == BP) mob += KnightOutpostMatrix[me][SquareTo64[from]]; } op[me] += mob; // space / piece invasion if (PAWN_RANK(from,me) >= Rank5){ piece_nb++; attackvalue += 1; } break; case Bishop64: // mobility mob = 0; // bishop mobility only considers forward mobility + 1 square for retreat // probably a very small elo gain if (colour == White){ for (to = from+15; capture=board->square[to], THROUGH(capture); to += 15) mob += MobMove; mob += unit[capture]; for (to = from+17; capture=board->square[to], THROUGH(capture); to += 17) mob += MobMove; mob += unit[capture]; if (board->square[from-15] != WP || board->square[from-17] != WP) mob++; } else { for (to = from-17; capture=board->square[to], THROUGH(capture); to -= 17) mob += MobMove; mob += unit[capture]; for (to = from-15; capture=board->square[to], THROUGH(capture); to -= 15) mob += MobMove; mob += unit[capture]; if (board->square[from+15] != BP || board->square[from+17] != BP) mob++; } op[me] += bishop_mob_opening[mob]; eg[me] += bishop_mob_endgame[mob]; // space if (PAWN_RANK(from,me) >= Rank5){ piece_nb++; attackvalue += 1; } break; case Rook64: // mobility mob = 0; for (to = from-16; capture=board->square[to], THROUGH(capture); to -= 16) mob += MobMove; mob += unit[capture]; for (to = from- 1; capture=board->square[to], THROUGH(capture); to -= 1) mob += MobMove; mob += unit[capture]; for (to = from+ 1; capture=board->square[to], THROUGH(capture); to += 1) mob += MobMove; mob += unit[capture]; for (to = from+16; capture=board->square[to], THROUGH(capture); to += 16) mob += MobMove; mob += unit[capture]; op[me] += rook_mob_opening[mob]; eg[me] += rook_mob_endgame[mob]; // open file if (UseOpenFile) { op[me] -= RookOpenFileOpening / 2; eg[me] -= RookOpenFileEndgame / 2; rook_file = SQUARE_FILE(from); if (board->pawn_file[me][rook_file] == 0) { // no friendly pawn op[me] += RookSemiOpenFileOpening; eg[me] += RookSemiOpenFileEndgame; if (board->pawn_file[opp][rook_file] == 0) { // no enemy pawn op[me] += RookOpenFileOpening - RookSemiOpenFileOpening; eg[me] += RookOpenFileEndgame - RookSemiOpenFileEndgame; } if ((mat_info->cflags[opp] & MatKingFlag) != 0) { king = KING_POS(board,opp); king_file = SQUARE_FILE(king); delta = abs(rook_file-king_file); // file distance if (delta <= 1) { op[me] += RookSemiKingFileOpening; if (delta == 0) op[me] += RookKingFileOpening - RookSemiKingFileOpening; } } } } // 7th rank if (PAWN_RANK(from,me) == Rank7) { if ((pawn_info->flags[opp] & BackRankFlag) != 0 // opponent pawn on 7th rank || PAWN_RANK(KING_POS(board,opp),me) == Rank8) { op[me] += Rook7thOpening; eg[me] += Rook7thEndgame; } } // space if (PAWN_RANK(from,me) >= Rank5){ piece_nb++; attackvalue += 2; } break; case Queen64: // mobility // we see how close we are to the opponent's king king = KING_POS(board,opp); king_file = SQUARE_FILE(king); king_rank = SQUARE_RANK(king); piece_file = SQUARE_FILE(from); piece_rank = SQUARE_RANK(from); new_mob = 10 - ((abs(king_file-piece_file) + abs(king_rank-piece_rank))); op[me] += /* (mob * QueenMobOpening) + */ new_mob; eg[me] += /* (mob * QueenMobEndgame) + */ new_mob; // 7th rank if (PAWN_RANK(from,me) == Rank7) { if ((pawn_info->flags[opp] & BackRankFlag) != 0 // opponent pawn on 7th rank || PAWN_RANK(KING_POS(board,opp),me) == Rank8) { op[me] += Queen7thOpening; eg[me] += Queen7thEndgame; } } // space if (PAWN_RANK(from,me) >= Rank5){ piece_nb++; attackvalue += 4; } break; } } // space / piece incasion op[me] += SSpaceWeight[piece_nb] * attackvalue; } // update *opening += ((op[White] - op[Black]) * PieceActivityWeight) / 256; *endgame += ((eg[White] - eg[Black]) * PieceActivityWeight) / 256; } // eval_king() static void eval_king(const board_t * board, const material_info_t * mat_info, int * opening, int * endgame) { int colour; int op[ColourNb], eg[ColourNb]; int me, opp; int from; int penalty_1, penalty_2; int tmp; int penalty; int king; const sq_t * ptr; int piece; int attack_tot; int piece_nb; int king_file, king_rank, file; ASSERT(board!=NULL); ASSERT(mat_info!=NULL); ASSERT(opening!=NULL); ASSERT(endgame!=NULL); // init for (colour = 0; colour < ColourNb; colour++) { op[colour] = 0; eg[colour] = 0; } // white pawn shelter if (UseShelter && (mat_info->cflags[White] & MatKingFlag) != 0) { // init penalty = 0; me = White; if (board->number[BlackQueen12] > 0){ // king penalty_1 = shelter_square(board,mat_info,KING_POS(board,me),me); // castling penalty_2 = penalty_1; if ((board->flags & FlagsWhiteKingCastle) != 0) { tmp = shelter_square(board,mat_info,G1,me); if (tmp < penalty_2) penalty_2 = tmp; } if ((board->flags & FlagsWhiteQueenCastle) != 0) { tmp = shelter_square(board,mat_info,B1,me); if (tmp < penalty_2) penalty_2 = tmp; } ASSERT(penalty_2>=0&&penalty_2<=penalty_1); // penalty penalty = (penalty_1 + penalty_2) / 2; ASSERT(penalty>=0); } // storm if (UseStorm) { file = SQUARE_FILE(KING_POS(board,White)); penalty += storm_file(board,file,White); if (file != FileA) penalty += storm_file(board,file-1,White); if (file != FileH) penalty += storm_file(board,file+1,White); } // add white king safety score to evaluation op[me] -= (penalty * ShelterOpening) / 256; } // black pawn shelter if (UseShelter && (mat_info->cflags[Black] & MatKingFlag) != 0) { penalty = 0; me = Black; if (board->number[WhiteQueen12] > 0){ // king penalty_1 = shelter_square(board,mat_info,KING_POS(board,me),me); // castling penalty_2 = penalty_1; if ((board->flags & FlagsBlackKingCastle) != 0) { tmp = shelter_square(board,mat_info,G8,me); if (tmp < penalty_2) penalty_2 = tmp; } if ((board->flags & FlagsBlackQueenCastle) != 0) { tmp = shelter_square(board,mat_info,B8,me); if (tmp < penalty_2) penalty_2 = tmp; } ASSERT(penalty_2>=0&&penalty_2<=penalty_1); // penalty penalty = (penalty_1 + penalty_2) / 2; ASSERT(penalty>=0); } // storm if (UseStorm) { file = SQUARE_FILE(KING_POS(board,Black)); penalty += storm_file(board,file,Black); if (file != FileA) penalty += storm_file(board,file-1,Black); if (file != FileH) penalty += storm_file(board,file+1,Black); } op[me] -= (penalty * ShelterOpening) / 256; } // king attacks if (UseKingAttack) { for (colour = 0; colour < ColourNb; colour++) { if ((mat_info->cflags[colour] & MatKingFlag) != 0) { me = colour; opp = COLOUR_OPP(me); king = KING_POS(board,me); king_file = SQUARE_FILE(king); king_rank = SQUARE_RANK(king); // piece attacks attack_tot = 0; piece_nb = 0; for (ptr = &board->piece[opp][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; if (piece_attack_king(board,piece,from,king)) { piece_nb++; attack_tot += KingAttackUnit[piece]; } /* else{ if ((abs(king_file-SQUARE_FILE(from)) + abs(king_rank-SQUARE_RANK(from))) <= 4){ piece_nb++; attack_tot += KingAttackUnit[piece]; } } */ } // scoring ASSERT(piece_nb>=0&&piece_nb<16); op[colour] -= (attack_tot * KingAttackOpening * KingAttackWeight[piece_nb]) / 256; } } } // update *opening += ((op[White] - op[Black]) * KingSafetyWeight) / 256; *endgame += ((eg[White] - eg[Black]) * KingSafetyWeight) / 256; } // eval_passer() static void eval_passer(const board_t * board, const pawn_info_t * pawn_info, int * opening, int * endgame) { int colour; int op[ColourNb], eg[ColourNb]; int att, def; int bits; int file, rank; int sq; int min, max; int delta; int white_passed_nb, black_passed_nb; ASSERT(board!=NULL); ASSERT(pawn_info!=NULL); ASSERT(opening!=NULL); ASSERT(endgame!=NULL); // init for (colour = 0; colour < ColourNb; colour++) { op[colour] = 0; eg[colour] = 0; } white_passed_nb = 0; black_passed_nb = 0; // passed pawns for (colour = 0; colour < ColourNb; colour++) { att = colour; def = COLOUR_OPP(att); for (bits = pawn_info->passed_bits[att]; bits != 0; bits &= bits-1) { file = BIT_FIRST(bits); ASSERT(file>=FileA&&file<=FileH); rank = BIT_LAST(board->pawn_file[att][file]); ASSERT(rank>=Rank2&&rank<=Rank7); sq = SQUARE_MAKE(file,rank); if (COLOUR_IS_BLACK(att)) sq = SQUARE_RANK_MIRROR(sq); ASSERT(PIECE_IS_PAWN(board->square[sq])); ASSERT(COLOUR_IS(board->square[sq],att)); // Thomas /* if (att == White){ if (board->piece_size[Black]-1 == board->number[BlackKnight12] && (file == FileA || file == FileH)){ eg[att] += 30; } } else{ if (board->piece_size[White]-1 == board->number[WhiteKnight12] && (file == FileA || file == FileH)){ eg[att] += 30; } } */ // opening scoring op[att] += quad(PassedOpeningMin,PassedOpeningMax,rank); // endgame scoring init min = PassedEndgameMin; max = PassedEndgameMax; delta = max - min; ASSERT(delta>0); // "dangerous" bonus if (board->piece_size[def] <= 1 // defender has no piece && (unstoppable_passer(board,sq,att) || king_passer(board,sq,att))) { delta += UnstoppablePasser; } else if (free_passer(board,sq,att)) { delta += FreePasser; } // king-distance bonus delta -= pawn_att_dist(sq,KING_POS(board,att),att) * AttackerDistance; delta += pawn_def_dist(sq,KING_POS(board,def),att) * DefenderDistance; // endgame scoring eg[att] += min; if (delta > 0) eg[att] += quad(0,delta,rank); } } // update /* if (white_passed_nb > 100){ op[White] = ((white_passed_nb / 10) * op[White]) / 100 + op[White]; eg[White] = ((white_passed_nb / 10) * eg[White]) / 100 + eg[White]; } if (black_passed_nb > 100){ op[Black] = ((black_passed_nb / 10) * op[Black]) / 100 + op[Black]; eg[Black] = ((black_passed_nb / 10) * eg[Black]) / 100 + eg[Black]; } */ *opening += ((op[White] - op[Black]) * PassedPawnWeight) / 256; *endgame += ((eg[White] - eg[Black]) * PassedPawnWeight) / 256; } // eval_pattern() static void eval_pattern(const board_t * board, int * opening, int * endgame) { ASSERT(board!=NULL); ASSERT(opening!=NULL); ASSERT(endgame!=NULL); // trapped bishop (7th rank) if ((board->square[A7] == WB && board->square[B6] == BP) || (board->square[B8] == WB && board->square[C7] == BP)) { *opening -= TrappedBishop; *endgame -= TrappedBishop; } if ((board->square[H7] == WB && board->square[G6] == BP) || (board->square[G8] == WB && board->square[F7] == BP)) { *opening -= TrappedBishop; *endgame -= TrappedBishop; } if ((board->square[A2] == BB && board->square[B3] == WP) || (board->square[B1] == BB && board->square[C2] == WP)) { *opening += TrappedBishop; *endgame += TrappedBishop; } if ((board->square[H2] == BB && board->square[G3] == WP) || (board->square[G1] == BB && board->square[F2] == WP)) { *opening += TrappedBishop; *endgame += TrappedBishop; } // trapped bishop (6th rank) if (board->square[A6] == WB && board->square[B5] == BP) { *opening -= TrappedBishop / 2; *endgame -= TrappedBishop / 2; } if (board->square[H6] == WB && board->square[G5] == BP) { *opening -= TrappedBishop / 2; *endgame -= TrappedBishop / 2; } if (board->square[A3] == BB && board->square[B4] == WP) { *opening += TrappedBishop / 2; *endgame += TrappedBishop / 2; } if (board->square[H3] == BB && board->square[G4] == WP) { *opening += TrappedBishop / 2; *endgame += TrappedBishop / 2; } // blocked bishop if (board->square[D2] == WP && board->square[D3] != Empty && board->square[C1] == WB) { *opening -= BlockedBishop; } if (board->square[E2] == WP && board->square[E3] != Empty && board->square[F1] == WB) { *opening -= BlockedBishop; } if (board->square[D7] == BP && board->square[D6] != Empty && board->square[C8] == BB) { *opening += BlockedBishop; } if (board->square[E7] == BP && board->square[E6] != Empty && board->square[F8] == BB) { *opening += BlockedBishop; } // blocked rook if ((board->square[C1] == WK || board->square[B1] == WK) && (board->square[A1] == WR || board->square[A2] == WR || board->square[B1] == WR)) { *opening -= BlockedRook; } if ((board->square[F1] == WK || board->square[G1] == WK) && (board->square[H1] == WR || board->square[H2] == WR || board->square[G1] == WR)) { *opening -= BlockedRook; } if ((board->square[C8] == BK || board->square[B8] == BK) && (board->square[A8] == BR || board->square[A7] == BR || board->square[B8] == BR)) { *opening += BlockedRook; } if ((board->square[F8] == BK || board->square[G8] == BK) && (board->square[H8] == BR || board->square[H7] == BR || board->square[G8] == BR)) { *opening += BlockedRook; } } // unstoppable_passer() static bool unstoppable_passer(const board_t * board, int pawn, int colour) { int me, opp; int file, rank; int king; int prom; const sq_t * ptr; int sq; int dist; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(pawn)); ASSERT(COLOUR_IS_OK(colour)); me = colour; opp = COLOUR_OPP(me); file = SQUARE_FILE(pawn); rank = PAWN_RANK(pawn,me); king = KING_POS(board,opp); // clear promotion path? for (ptr = &board->piece[me][0]; (sq=*ptr) != SquareNone; ptr++) { if (SQUARE_FILE(sq) == file && PAWN_RANK(sq,me) > rank) { return false; // "friendly" blocker } } // init if (rank == Rank2) { pawn += PAWN_MOVE_INC(me); rank++; ASSERT(rank==PAWN_RANK(pawn,me)); } ASSERT(rank>=Rank3&&rank<=Rank7); prom = PAWN_PROMOTE(pawn,me); dist = DISTANCE(pawn,prom); ASSERT(dist==Rank8-rank); if (board->turn == opp) dist++; if (DISTANCE(king,prom) > dist) return true; // not in the square return false; } // king_passer() static bool king_passer(const board_t * board, int pawn, int colour) { int me; int king; int file; int prom; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(pawn)); ASSERT(COLOUR_IS_OK(colour)); me = colour; king = KING_POS(board,me); file = SQUARE_FILE(pawn); prom = PAWN_PROMOTE(pawn,me); if (DISTANCE(king,prom) <= 1 && DISTANCE(king,pawn) <= 1 && (SQUARE_FILE(king) != file || (file != FileA && file != FileH))) { return true; } return false; } // free_passer() static bool free_passer(const board_t * board, int pawn, int colour) { int me, opp; int inc; int sq; int move; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(pawn)); ASSERT(COLOUR_IS_OK(colour)); me = colour; opp = COLOUR_OPP(me); inc = PAWN_MOVE_INC(me); sq = pawn + inc; ASSERT(SQUARE_IS_OK(sq)); if (board->square[sq] != Empty) return false; move = MOVE_MAKE(pawn,sq); if (see_move(move,board) < 0) return false; return true; } // pawn_att_dist() static int pawn_att_dist(int pawn, int king, int colour) { int me; int inc; int target; ASSERT(SQUARE_IS_OK(pawn)); ASSERT(SQUARE_IS_OK(king)); ASSERT(COLOUR_IS_OK(colour)); me = colour; inc = PAWN_MOVE_INC(me); target = pawn + inc; return DISTANCE(king,target); } // pawn_def_dist() static int pawn_def_dist(int pawn, int king, int colour) { int me; int inc; int target; ASSERT(SQUARE_IS_OK(pawn)); ASSERT(SQUARE_IS_OK(king)); ASSERT(COLOUR_IS_OK(colour)); me = colour; inc = PAWN_MOVE_INC(me); target = pawn + inc; return DISTANCE(king,target); } // draw_init_list() static void draw_init_list(int list[], const board_t * board, int pawn_colour) { int pos; int att, def; const sq_t * ptr; int sq; int pawn; int i; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(COLOUR_IS_OK(pawn_colour)); // init pos = 0; att = pawn_colour; def = COLOUR_OPP(att); ASSERT(board->pawn_size[att]==1); ASSERT(board->pawn_size[def]==0); // att for (ptr = &board->piece[att][0]; (sq=*ptr) != SquareNone; ptr++) { list[pos++] = sq; } for (ptr = &board->pawn[att][0]; (sq=*ptr) != SquareNone; ptr++) { list[pos++] = sq; } // def for (ptr = &board->piece[def][0]; (sq=*ptr) != SquareNone; ptr++) { list[pos++] = sq; } for (ptr = &board->pawn[def][0]; (sq=*ptr) != SquareNone; ptr++) { list[pos++] = sq; } // end marker ASSERT(pos==board->piece_nb); list[pos] = SquareNone; // file flip? pawn = board->pawn[att][0]; if (SQUARE_FILE(pawn) >= FileE) { for (i = 0; i < pos; i++) { list[i] = SQUARE_FILE_MIRROR(list[i]); } } // rank flip? if (COLOUR_IS_BLACK(pawn_colour)) { for (i = 0; i < pos; i++) { list[i] = SQUARE_RANK_MIRROR(list[i]); } } } // draw_kpkq() static bool draw_kpkq(const int list[], int turn) { int wk, wp, bk, bq; int prom; int dist; // int wp_file, wp_rank; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); bq = *list++; ASSERT(SQUARE_IS_OK(bq)); ASSERT(*list==SquareNone); // test if (false) { } else if (wp == A7) { prom = A8; dist = 4; if (wk == B7 || wk == B8) { // best case if (COLOUR_IS_WHITE(turn)) dist--; } else if (wk == A8 || ((wk == C7 || wk == C8) && bq != A8)) { // white loses a tempo if (COLOUR_IS_BLACK(turn) && SQUARE_FILE(bq) != FileB) return false; } else { return false; } ASSERT(bq!=prom); if (DISTANCE(bk,prom) > dist) return true; } else if (wp == C7) { prom = C8; dist = 4; if (false) { } else if (wk == C8) { // dist = 0 dist++; // self-blocking penalty if (COLOUR_IS_WHITE(turn)) dist--; // right-to-move bonus } else if (wk == B7 || wk == B8) { // dist = 1, right side dist--; // right-side bonus if (DELTA_INC_LINE(wp-bq) == wk-wp) dist++; // pinned-pawn penalty if (COLOUR_IS_WHITE(turn)) dist--; // right-to-move bonus } else if (wk == D7 || wk == D8) { // dist = 1, wrong side if (DELTA_INC_LINE(wp-bq) == wk-wp) dist++; // pinned-pawn penalty if (COLOUR_IS_WHITE(turn)) dist--; // right-to-move bonus } else if ((wk == A7 || wk == A8) && bq != C8) { // dist = 2, right side if (COLOUR_IS_BLACK(turn) && SQUARE_FILE(bq) != FileB) return false; dist--; // right-side bonus } else if ((wk == E7 || wk == E8) && bq != C8) { // dist = 2, wrong side if (COLOUR_IS_BLACK(turn) && SQUARE_FILE(bq) != FileD) return false; } else { return false; } ASSERT(bq!=prom); if (DISTANCE(bk,prom) > dist) return true; } return false; } // draw_kpkr() static bool draw_kpkr(const int list[], int turn) { int wk, wp, bk, br; int wk_file, wk_rank; int wp_file, wp_rank; int br_file, br_rank; int inc; int prom; int dist; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); br = *list++; ASSERT(SQUARE_IS_OK(br)); ASSERT(*list==SquareNone); // init wk_file = SQUARE_FILE(wk); wk_rank = SQUARE_RANK(wk); wp_file = SQUARE_FILE(wp); wp_rank = SQUARE_RANK(wp); br_file = SQUARE_FILE(br); br_rank = SQUARE_RANK(br); inc = PAWN_MOVE_INC(White); prom = PAWN_PROMOTE(wp,White); // conditions if (false) { } else if (DISTANCE(wk,wp) == 1) { ASSERT(abs(wk_file-wp_file)<=1); ASSERT(abs(wk_rank-wp_rank)<=1); // no-op } else if (DISTANCE(wk,wp) == 2 && abs(wk_rank-wp_rank) <= 1) { ASSERT(abs(wk_file-wp_file)==2); ASSERT(abs(wk_rank-wp_rank)<=1); if (COLOUR_IS_BLACK(turn) && br_file != (wk_file + wp_file) / 2) return false; } else { return false; } // white features dist = DISTANCE(wk,prom) + DISTANCE(wp,prom); if (wk == prom) dist++; if (wk == wp+inc) { // king on pawn's "front square" if (wp_file == FileA) return false; dist++; // self-blocking penalty } // black features if (br_file != wp_file && br_rank != Rank8) { dist--; // misplaced-rook bonus } // test if (COLOUR_IS_WHITE(turn)) dist--; // right-to-move bonus if (DISTANCE(bk,prom) > dist) return true; return false; } // draw_kpkb() static bool draw_kpkb(const int list[], int turn) { int wk, wp, bk, bb; int inc; int end, to; int delta, inc_2; int sq; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); bb = *list++; ASSERT(SQUARE_IS_OK(bb)); ASSERT(*list==SquareNone); // blocked pawn? inc = PAWN_MOVE_INC(White); end = PAWN_PROMOTE(wp,White) + inc; for (to = wp+inc; to != end; to += inc) { ASSERT(SQUARE_IS_OK(to)); if (to == bb) return true; // direct blockade delta = to - bb; ASSERT(delta_is_ok(delta)); if (PSEUDO_ATTACK(BB,delta)) { inc_2 = DELTA_INC_ALL(delta); ASSERT(inc_2!=IncNone); sq = bb; do { sq += inc_2; ASSERT(SQUARE_IS_OK(sq)); ASSERT(sq!=wk); ASSERT(sq!=wp); ASSERT(sq!=bb); if (sq == to) return true; // indirect blockade } while (sq != bk); } } return false; } // draw_kpkn() static bool draw_kpkn(const int list[], int turn) { int wk, wp, bk, bn; int inc; int end; int file; int sq; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); bn = *list++; ASSERT(SQUARE_IS_OK(bn)); ASSERT(*list==SquareNone); // blocked pawn? inc = PAWN_MOVE_INC(White); end = PAWN_PROMOTE(wp,White) + inc; file = SQUARE_FILE(wp); if (file == FileA || file == FileH) end -= inc; for (sq = wp+inc; sq != end; sq += inc) { ASSERT(SQUARE_IS_OK(sq)); if (sq == bn || PSEUDO_ATTACK(BN,sq-bn)) return true; // blockade } return false; } // draw_knpk() static bool draw_knpk(const int list[], int turn) { int wk, wn, wp, bk; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wn = *list++; ASSERT(SQUARE_IS_OK(wn)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); ASSERT(*list==SquareNone); // test if (wp == A7 && DISTANCE(bk,A8) <= 1) return true; return false; } // draw_krpkr() static bool draw_krpkr(const int list[], int turn) { int wk, wr, wp, bk, br; int wp_file, wp_rank; int bk_file, bk_rank; int br_file, br_rank; int prom; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wr = *list++; ASSERT(SQUARE_IS_OK(wr)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); br = *list++; ASSERT(SQUARE_IS_OK(br)); ASSERT(*list==SquareNone); // test wp_file = SQUARE_FILE(wp); wp_rank = SQUARE_RANK(wp); bk_file = SQUARE_FILE(bk); bk_rank = SQUARE_RANK(bk); br_file = SQUARE_FILE(br); br_rank = SQUARE_RANK(br); prom = PAWN_PROMOTE(wp,White); if (false) { } else if (bk == prom) { // TODO: rook near Rank1 if wp_rank == Rank6? if (br_file > wp_file) return true; } else if (bk_file == wp_file && bk_rank > wp_rank) { return true; } else if (wr == prom && wp_rank == Rank7 && (bk == G7 || bk == H7) && br_file == wp_file) { if (br_rank <= Rank3) { if (DISTANCE(wk,wp) > 1) return true; } else { // br_rank >= Rank4 if (DISTANCE(wk,wp) > 2) return true; } } return false; } // draw_kbpkb() static bool draw_kbpkb(const int list[], int turn) { int wk, wb, wp, bk, bb; int inc; int end, to; int delta, inc_2; int sq; ASSERT(list!=NULL); ASSERT(COLOUR_IS_OK(turn)); // load wk = *list++; ASSERT(SQUARE_IS_OK(wk)); wb = *list++; ASSERT(SQUARE_IS_OK(wb)); wp = *list++; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_FILE(wp)<=FileD); bk = *list++; ASSERT(SQUARE_IS_OK(bk)); bb = *list++; ASSERT(SQUARE_IS_OK(bb)); ASSERT(*list==SquareNone); // opposit colour? if (SQUARE_COLOUR(wb) == SQUARE_COLOUR(bb)) return false; // TODO // blocked pawn? inc = PAWN_MOVE_INC(White); end = PAWN_PROMOTE(wp,White) + inc; for (to = wp+inc; to != end; to += inc) { ASSERT(SQUARE_IS_OK(to)); if (to == bb) return true; // direct blockade delta = to - bb; ASSERT(delta_is_ok(delta)); if (PSEUDO_ATTACK(BB,delta)) { inc_2 = DELTA_INC_ALL(delta); ASSERT(inc_2!=IncNone); sq = bb; do { sq += inc_2; ASSERT(SQUARE_IS_OK(sq)); ASSERT(sq!=wk); ASSERT(sq!=wb); ASSERT(sq!=wp); ASSERT(sq!=bb); if (sq == to) return true; // indirect blockade } while (sq != bk); } } return false; } // shelter_square() static int shelter_square(const board_t * board, const material_info_t * mat_info, int square, int colour) { int penalty; int file, rank; int type; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(COLOUR_IS_OK(colour)); penalty = 0; file = SQUARE_FILE(square); rank = PAWN_RANK(square,colour); penalty += shelter_file(board,file,rank,colour,TypeShelterFront); if (file != FileA){ if (file > FileE) penalty += shelter_file(board,file-1,rank,colour,TypeShelterOpen); else penalty += shelter_file(board,file-1,rank,colour,TypeShelterClosed); } if (file != FileH){ if (file < FileD) penalty += shelter_file(board,file+1,rank,colour,TypeShelterOpen); else penalty += shelter_file(board,file+1,rank,colour,TypeShelterClosed); } if (penalty == 0) penalty = 11; // weak back rank if (UseStorm) { penalty += storm_file(board,file,colour); if (file != FileA) penalty += storm_file(board,file-1,colour); if (file != FileH) penalty += storm_file(board,file+1,colour); } return penalty; } // shelter_file() static int shelter_file(const board_t * board, int file, int rank, int colour, int type) { int dist; ASSERT(board!=NULL); ASSERT(file>=FileA&&file<=FileH); ASSERT(rank>=Rank1&&rank<=Rank8); ASSERT(COLOUR_IS_OK(colour)); dist = BIT_FIRST(board->pawn_file[colour][file]&BitGE[rank]); ASSERT(dist>=Rank2&&dist<=Rank8); dist = Rank8 - dist; ASSERT(dist>=0&&dist<=6); if (type == TypeShelterFront) return PawnShelterFront[dist]; else if (type == TypeShelterOpen) return PawnShelterOpenSide[dist]; else return PawnShelterClosedSide[dist]; } // storm_file() static int storm_file(const board_t * board, int file, int colour) { int dist; int penalty; ASSERT(board!=NULL); ASSERT(file>=FileA&&file<=FileH); ASSERT(COLOUR_IS_OK(colour)); dist = BIT_LAST(board->pawn_file[COLOUR_OPP(colour)][file]); ASSERT(dist>=Rank1&&dist<=Rank7); penalty = 0; switch (dist) { case Rank4: penalty = StormOpening * 1; break; case Rank5: penalty = StormOpening * 2; break; case Rank6: penalty = StormOpening * 3; break; } return penalty; } // bishop_can_attack() static bool bishop_can_attack(const board_t * board, int to, int colour) { const sq_t * ptr; int from; int piece; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(COLOUR_IS_OK(colour)); for (ptr = &board->piece[colour][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; if (PIECE_IS_BISHOP(piece) && SQUARE_COLOUR(from) == SQUARE_COLOUR(to)) { return true; } } return false; } // end of eval.cpp toga2-3.0.0.1SE1/src/search_full.cpp0000644000175000017500000012201112120153040016323 0ustar oliveroliver// search_full.cpp // includes #include #include "pawn.h" #include "attack.h" #include "board.h" #include "colour.h" #include "eval.h" #include "list.h" #include "move.h" #include "move_check.h" #include "move_do.h" #include "option.h" #include "piece.h" #include "pst.h" #include "pv.h" #include "recog.h" #include "search.h" #include "search_full.h" #include "see.h" #include "sort.h" #include "trans.h" #include "util.h" #include "value.h" #include "probe.h" #define ABS(x) ((x)<0?-(x):(x)) #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) // #define R_adpt(max_pieces, depth, Reduction) (Reduction + ((depth) > (9 + ((max_pieces<3) ? 2 : 0)))) // constants and variables // main search static const bool UseDistancePruning = true; // transposition table static const bool UseTrans = true; static const int TransDepth = 1; static const bool UseExact = true; static const bool UseMateValues = true; // use mate values from shallower searches? // null move static /* const */ bool UseNull = true; static /* const */ bool UseNullEval = true; // true static const int NullDepth = 2; // was 2 static /* const */ int NullReduction = 3; static /* const */ bool UseVer = true; static /* const */ bool UseVerEndgame = true; // true static /* const */ int VerReduction = 5; // was 3 // move ordering static const bool UseIID = true; static const int IIDDepth = 3; static const int IIDReduction = 2; // extensions static const bool ExtendSingleReply = true; // true // razoring static const int RazorDepth = 1; static const int RazorMargin = 300; // history pruning static /* const */ bool UseHistory = true; static const int HistoryDepth = 3; // was 3 static const int HistoryPVDepth = 3; // was 3 static const int HistoryMoveNb = 3; // was 3 static /* const */ int HistoryValue = 9830; // 60% //static /* const */ int HistoryBound = 6400; // * 16384 + 50) / 100 10%=1638 15%=2458 20%=3277 //static /* const */ bool UseExtendedHistory = true; //static const bool HistoryReSearch = true; // Late Move Reductions (Stockfish/Protector) static int quietPvMoveReduction[64][64]; /* [depth][played move count] */ static int quietMoveReduction[64][64]; /* [depth][played move count] */ // futility pruning static /* const */ bool UseFutility = true; // false static const int FutilityMargin = 100; static /* const */ int FutilityMargin1 = 100; static /* const */ int FutilityMargin2 = 200; // Chris Formula's setting; was 300 static /* const */ int FutilityMargin3 = 950; // quiescence search static /* const */ bool UseDelta = true; // false static /* const */ int DeltaMargin = 50; //static /* const */ int CheckNb = 1; //static /* const */ int CheckDepth = 0; // 1 - CheckNb // misc static const int NodeAll = -1; static const int NodePV = 0; static const int NodeCut = +1; // macros #define NODE_OPP(type) (-(type)) #define DEPTH_MATCH(d1,d2) ((d1)>=(d2)) // prototypes static int full_root (list_t * list, board_t * board, int alpha, int beta, int depth, int height, int search_type, int ThreadId); static int full_search (board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int node_type, bool extended, int ThreadId); static int full_no_null (board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int node_type, int trans_move, int * best_move, bool extended, int ThreadId); static int full_quiescence (board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int ThreadId); static int full_new_depth (int depth, int move, board_t * board, bool single_reply, bool in_pv, int height, bool extended, bool * cap_extended, int ThreadId); static bool do_null (const board_t * board); static bool do_ver (const board_t * board); static void pv_fill (const mv_t pv[], board_t * board); static bool move_is_dangerous (int move, const board_t * board); static bool capture_is_dangerous (int move, const board_t * board); static bool simple_stalemate (const board_t * board); static bool passed_pawn_move (int move, const board_t * board); static bool is_passed (const board_t * board, int to); // functions // search_full_init() void search_full_init(list_t * list, board_t * board, int ThreadId) { const char * string; int trans_move, trans_depth, trans_flags, trans_value; entry_t * found_entry; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); // null-move options string = option_get_string("NullMove Pruning"); if (false) { } else if (my_string_equal(string,"Always")) { UseNull = true; UseNullEval = false; } else if (my_string_equal(string,"Fail High")) { UseNull = true; UseNullEval = true; } else if (my_string_equal(string,"Never")) { UseNull = false; UseNullEval = false; } else { ASSERT(false); UseNull = true; UseNullEval = true; } NullReduction = option_get_int("NullMove Reduction"); string = option_get_string("Verification Search"); if (false) { } else if (my_string_equal(string,"Always")) { UseVer = true; UseVerEndgame = false; } else if (my_string_equal(string,"Endgame")) { UseVer = true; UseVerEndgame = true; } else if (my_string_equal(string,"Never")) { UseVer = false; UseVerEndgame = false; } else { ASSERT(false); UseVer = true; UseVerEndgame = true; } VerReduction = option_get_int("Verification Reduction"); // history-pruning options UseHistory = option_get_bool("History Pruning"); HistoryValue = (option_get_int("History Threshold") * 16384 + 50) / 100; //UseExtendedHistory = option_get_bool("Toga Extended History Pruning"); //HistoryBound = (option_get_int("Toga History Threshold") * 16384 + 50) / 100; // Stockfish/Protector Late Move Reductions // about 20 elo better than previous Toga History Reductions int i, j; for (i = 0; i < 64; i++){ for (j = 0; j < 64; j++){ if (i == 0 || j == 0){ quietPvMoveReduction[i][j] = quietMoveReduction[i][j] = 0; } else{ double pvReduction = log((double) (i)) * log((double) (j)) / 3.0; double nonPvReduction = 0.33 + log((double) (i)) * log((double) (j)) / 2.25; quietPvMoveReduction[i][j] = (int) (pvReduction >= 1.0 ? floor(pvReduction) : 0); quietMoveReduction[i][j] = (int) (nonPvReduction >= 1.0 ? floor(nonPvReduction) : 0); } } } // futility-pruning options UseFutility = option_get_bool("Futility Pruning"); FutilityMargin1 = option_get_int("Futility Margin"); FutilityMargin2 = option_get_int("Extended Futility Margin"); // delta-pruning options UseDelta = option_get_bool("Delta Pruning"); DeltaMargin = option_get_int("Delta Margin"); // quiescence-search options SearchCurrent[ThreadId]->CheckNb = option_get_int("Quiescence Check Plies"); SearchCurrent[ThreadId]->CheckDepth = 1 - SearchCurrent[ThreadId]->CheckNb; // standard sort list_note(list); list_sort(list); // basic sort trans_move = MoveNone; if (UseTrans) trans_retrieve(Trans,&found_entry,board->key,&trans_move,&trans_depth,&trans_flags,&trans_value); note_moves(list,board,0,trans_move,ThreadId); list_sort(list); } // search_full_root() int search_full_root(list_t * list, board_t * board, int a, int b, int depth, int search_type, int ThreadId) { int value; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); ASSERT(depth_is_ok(depth)); ASSERT(search_type==SearchNormal||search_type==SearchShort); ASSERT(list==SearchRoot[ThreadId]->list); ASSERT(!LIST_IS_EMPTY(list)); ASSERT(board==SearchCurrent[ThreadId]->board); ASSERT(board_is_legal(board)); ASSERT(depth>=1); value = full_root(list,board,a,b,depth,0,search_type, ThreadId); ASSERT(value_is_ok(value)); ASSERT(LIST_VALUE(list,0)==value); return value; } // full_root() static int full_root(list_t * list, board_t * board, int alpha, int beta, int depth, int height, int search_type, int ThreadId) { int old_alpha; int value, best_value[MultiPVMax]; int i, move, j; int new_depth; undo_t undo[1]; mv_t new_pv[HeightMax]; bool found; bool cap_extended; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); ASSERT(range_is_ok(alpha,beta)); ASSERT(depth_is_ok(depth)); ASSERT(height_is_ok(height)); ASSERT(search_type==SearchNormal||search_type==SearchShort); ASSERT(list==SearchRoot[ThreadId]->list); ASSERT(!LIST_IS_EMPTY(list)); ASSERT(board==SearchCurrent[ThreadId]->board); ASSERT(board_is_legal(board)); ASSERT(depth>=1); // init SearchCurrent[ThreadId]->node_nb++; SearchInfo[ThreadId]->check_nb--; if (SearchCurrent[ThreadId]->multipv == 0) for (i = 0; i < LIST_SIZE(list); i++) list->value[i] = ValueNone; old_alpha = alpha; best_value[SearchCurrent[ThreadId]->multipv] = ValueNone; // move loop for (i = 0; i < LIST_SIZE(list); i++) { move = LIST_MOVE(list,i); if (SearchCurrent[ThreadId]->multipv > 0){ found = false; for (j = 0; j < SearchCurrent[ThreadId]->multipv; j++){ if (SearchBest[ThreadId][j].pv[0] == move){ found = true; break; } } if (found == true) continue; } SearchRoot[ThreadId]->depth = depth; SearchRoot[ThreadId]->move = move; SearchRoot[ThreadId]->move_pos = i; SearchRoot[ThreadId]->move_nb = LIST_SIZE(list); search_update_root(ThreadId); new_depth = full_new_depth(depth,move,board,board_is_check(board)&&LIST_SIZE(list)==1,true, height, false, &cap_extended,ThreadId); //new_depth1 = full_new_depth(depth,move,board,board_is_check(board)&&LIST_SIZE(list)==1,false, height, ThreadId); move_do(board,move,undo); // search move. Changed by Jerry Donald to use aspiration windows (no Inf window researches needed) if (search_type == SearchShort || best_value[SearchCurrent[ThreadId]->multipv] == ValueNone) { // first move value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NodePV,cap_extended,ThreadId); } else { // other moves value = -full_search(board,-alpha-1,-alpha,new_depth,height+1,new_pv,NodeCut,cap_extended,ThreadId); if (value > alpha) { // && value < beta SearchRoot[ThreadId]->change = true; SearchRoot[ThreadId]->easy = false; SearchRoot[ThreadId]->flag = false; search_update_root(ThreadId); value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NodePV,cap_extended,ThreadId); } } move_undo(board,move,undo); if (value <= alpha) { // upper bound list->value[i] = old_alpha; } else if (value >= beta) { // lower bound list->value[i] = beta; } else { // alpha < value < beta => exact value list->value[i] = value; } if (value > best_value[SearchCurrent[ThreadId]->multipv] && (best_value[SearchCurrent[ThreadId]->multipv] == ValueNone || value > alpha)) { SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].move = move; SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].value = value; if (value <= alpha) { // upper bound SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].flags = SearchUpper; } else if (value >= beta) { // lower bound SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].flags = SearchLower; } else { // alpha < value < beta => exact value SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].flags = SearchExact; } SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].depth = depth; pv_cat(SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].pv,new_pv,move); search_update_best(ThreadId); } if (value > best_value[SearchCurrent[ThreadId]->multipv]) { best_value[SearchCurrent[ThreadId]->multipv] = value; if (value > alpha) { if (search_type == SearchNormal) alpha = value; if (value >= beta) break; } } } ASSERT(value_is_ok(best_value)); list_sort(list); ASSERT(SearchBest[ThreadId]->move==LIST_MOVE(list,0)); ASSERT(SearchBest[ThreadId]->value==best_value); if (UseTrans && best_value[SearchCurrent[ThreadId]->multipv] > old_alpha && best_value[SearchCurrent[ThreadId]->multipv] < beta) { pv_fill(SearchBest[ThreadId][SearchCurrent[ThreadId]->multipv].pv,board); } return best_value[SearchCurrent[ThreadId]->multipv]; } // full_search() static int full_search(board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int node_type, bool extended, int ThreadId) { bool in_check; bool single_reply; bool good_cap; int trans_move, trans_depth, trans_flags, trans_value; int old_alpha; int value, best_value; int move, best_move; int new_depth; int played_nb; int i; int opt_value; bool reduced, cap_extended; attack_t attack[1]; sort_t sort[1]; undo_t undo[1]; mv_t new_pv[HeightMax]; mv_t played[256]; int FutilityMargin; int probe_score, probe_depth; int newHistoryValue; int threshold; int reduction; entry_t * found_entry; ASSERT(board!=NULL); ASSERT(range_is_ok(alpha,beta)); ASSERT(depth_is_ok(depth)); ASSERT(height_is_ok(height)); ASSERT(pv!=NULL); ASSERT(node_type==NodePV||node_type==NodeCut||node_type==NodeAll); ASSERT(board_is_legal(board)); // horizon? if (depth <= 0){ if (node_type == NodePV) SearchCurrent[ThreadId]->CheckDepth = 1 - SearchCurrent[ThreadId]->CheckNb - 1; else SearchCurrent[ThreadId]->CheckDepth = 1 - SearchCurrent[ThreadId]->CheckNb; return full_quiescence(board,alpha,beta,0,height,pv,ThreadId); } // init SearchCurrent[ThreadId]->node_nb++; SearchInfo[ThreadId]->check_nb--; PV_CLEAR(pv); if (height > SearchCurrent[ThreadId]->max_depth) SearchCurrent[ThreadId]->max_depth = height; if (SearchInfo[ThreadId]->check_nb <= 0) { SearchInfo[ThreadId]->check_nb += SearchInfo[ThreadId]->check_inc; search_check(ThreadId); } // draw? if (board_is_repetition(board)) return ValueDraw; /* Interior node recognizer from scorpio by Daniel Shawul -> dont probe at the leaves as this will slow down search For 4/3 pieces probe there also. -> After captures and pawn moves assume exact score and cutoff tree, because we are making progress. Note this is not done only for speed. -> if we are far from root (depth / 2), assume exact score and cutoff tree */ if (egbb_is_loaded && board->piece_nb <= 5){ probe_depth = (2 * SearchCurrent[ThreadId]->act_iteration) / 3; if ((board->piece_nb <=4 || height <= probe_depth) && (height >= probe_depth || board->cap_sq != SquareNone || PIECE_IS_PAWN(board->moving_piece)) ) { if (probe_bitbases(board, probe_score)){ if (probe_score < 0 && board_is_mate(board)) return VALUE_MATE(height); probe_score = value_from_trans(probe_score,height); /* trans_move = MoveNone; trans_depth = depth; trans_flags = TransUnknown; if (probe_score > alpha) trans_flags |= TransLower; if (probe_score < beta) trans_flags |= TransUpper; trans_store(Trans,board->key,trans_move,trans_depth,trans_flags,probe_score);*/ return probe_score; } } } if (recog_draw(board,ThreadId)) return ValueDraw; // mate-distance pruning if (UseDistancePruning) { // lower bound value = VALUE_MATE(height+2); // does not work if the current position is mate if (value > alpha && board_is_mate(board)) value = VALUE_MATE(height); if (value > alpha) { alpha = value; if (value >= beta) return value; } // upper bound value = -VALUE_MATE(height+1); if (value < beta) { beta = value; if (value <= alpha) return value; } } // transposition table trans_move = MoveNone; if (UseTrans && depth >= TransDepth) { if (trans_retrieve(Trans,&found_entry,board->key,&trans_move,&trans_depth,&trans_flags,&trans_value)) { // trans_move is now updated /* if (found_entry->depth != trans_depth){ found_entry->depth = trans_depth; }*/ if (node_type != NodePV /*|| ThreadId > 0*/) { if (UseMateValues) { if (trans_depth < depth) { if (trans_value < -ValueEvalInf && TRANS_IS_UPPER(trans_flags)) { trans_depth = depth; trans_flags = TransUpper; } else if (trans_value > +ValueEvalInf && TRANS_IS_LOWER(trans_flags)) { trans_depth = depth; trans_flags = TransLower; } } if (trans_depth >= depth) { trans_value = value_from_trans(trans_value,height); if ((UseExact && TRANS_IS_EXACT(trans_flags)) || (TRANS_IS_LOWER(trans_flags) && trans_value >= beta) || (TRANS_IS_UPPER(trans_flags) && trans_value <= alpha)) { return trans_value; } /* if (TRANS_IS_EXACT(trans_flags)) return trans_value; if (TRANS_IS_LOWER(trans_flags)) { if (trans_value >= beta) return trans_value; if (trans_value > alpha) alpha = trans_value; } if (TRANS_IS_UPPER(trans_flags)) { if (trans_value <= alpha) return trans_value; if (trans_value < beta) beta = trans_value; } */ } } } } } // height limit if (height >= HeightMax-1) return eval(board, alpha, beta, ThreadId); // more init old_alpha = alpha; best_value = ValueNone; best_move = MoveNone; played_nb = 0; attack_set(attack,board); in_check = ATTACK_IN_CHECK(attack); // null-move pruning if (UseNull && depth >= NullDepth && node_type != NodePV && !(TRANS_IS_UPPER(trans_flags) && trans_depth >= depth - NullReduction - 1 && trans_value < beta)) { // if hash table tells us we are < beta, the null move search probably watses time if (!in_check && !value_is_mate(beta) && do_null(board) && (!UseNullEval || depth <= NullReduction+1 || eval(board,alpha, beta, ThreadId) >= beta)) { // null-move search // if (depth < 11) new_depth = depth - NullReduction - 1; // else // new_depth = depth - NullReduction - 2; //new_depth = depth - R_adpt(board->piece_size[board->turn]+board->pawn_size[board->turn],depth,NullReduction) - 1; move_do_null(board,undo); value = -full_search(board,-beta,-beta+1,new_depth,height+1,new_pv,NODE_OPP(node_type),false,ThreadId); move_undo_null(board,undo); // verification search if (UseVer && depth > VerReduction) { if (value >= beta && (!UseVerEndgame || do_ver(board))) { new_depth = depth - VerReduction; ASSERT(new_depth>0); value = full_no_null(board,alpha,beta,new_depth,height,new_pv,NodeCut,trans_move,&move,false,ThreadId); if (value >= beta) { ASSERT(move==new_pv[0]); played[played_nb++] = move; best_move = move; best_value = value; pv_copy(pv,new_pv); goto cut; } } } // pruning if (value >= beta) { if (value > +ValueEvalInf) value = +ValueEvalInf; // do not return unproven mates ASSERT(!value_is_mate(value)); // pv_cat(pv,new_pv,MoveNull); best_move = MoveNone; best_value = value; goto cut; } } } // Razoring: idea by Tord Romstad (Glaurung), fixed by Jerry Donald if (node_type != NodePV && !in_check && trans_move == MoveNone && depth <= 3){ threshold = beta - RazorMargin - (depth-1)*39; // Values from Protector (Raimund Heid) if (eval(board,threshold-1, threshold, ThreadId) < threshold){ value = full_quiescence(board,threshold-1,threshold,0,height,pv,ThreadId); if (value < threshold) // corrected - was < beta which is too risky at depth > 1 return value; } } // Internal Iterative Deepening if (UseIID && depth >= IIDDepth && node_type == NodePV && trans_move == MoveNone) { // new_depth = depth - IIDReduction; new_depth = MIN(depth - IIDReduction,depth/2); ASSERT(new_depth>0); value = full_search(board,alpha,beta,new_depth,height,new_pv,node_type,false,ThreadId); if (value <= alpha) value = full_search(board,-ValueInf,beta,new_depth,height,new_pv,node_type,false,ThreadId); trans_move = new_pv[0]; } // move generation sort_init(sort,board,attack,depth,height,trans_move,ThreadId); single_reply = false; if (in_check && LIST_SIZE(sort->list) == 1) single_reply = true; // HACK // move loop opt_value = +ValueInf; good_cap = true; while ((move=sort_next(sort,ThreadId)) != MoveNone) { // extensions new_depth = full_new_depth(depth,move,board,single_reply,node_type==NodePV, height, extended, &cap_extended, ThreadId); // history pruning value = sort->value; // history score if (!in_check && depth <= 6 && node_type != NodePV && new_depth < depth && value < 2 * HistoryValue / (depth + depth % 2) /*2*/ && played_nb >= 1+depth && !move_is_dangerous(move,board)){ continue; } // futility pruning if (UseFutility && node_type != NodePV && depth <= 5) { if (!in_check && new_depth < depth && !move_is_tactical(move,board) && !move_is_dangerous(move,board)) { ASSERT(!move_is_check(move,board)); // optimistic evaluation (Chris Formula) if (opt_value == +ValueInf) { if (depth>=2){ FutilityMargin = FutilityMargin2 + (depth % 2) * 100; } else{ FutilityMargin = FutilityMargin1; } opt_value = eval(board,alpha-FutilityMargin,alpha,ThreadId) + FutilityMargin; ASSERT(opt_value<+ValueInf); } value = opt_value; // pruning if (value <= alpha) { if (value > best_value) { best_value = value; PV_CLEAR(pv); } continue; } } } // Late Move Reductions // init reduced = false; reduction = 0; // lookup reduction if (UseHistory) { if (!in_check && new_depth < depth && played_nb >= HistoryMoveNb && depth >= HistoryDepth && !move_is_dangerous(move,board)) { if (good_cap && !move_is_tactical(move,board)){ good_cap = false; } if (!good_cap){ reduction = (node_type == NodePV ? quietPvMoveReduction[depth<64 ? depth: 63][played_nb<64? played_nb: 63]: quietMoveReduction[depth<64 ? depth: 63][played_nb<64? played_nb: 63]); if (reduction > 0) reduced = true; } } } // recursive search move_do(board,move,undo); if (node_type != NodePV || best_value == ValueNone) { // first move or non-pv value = -full_search(board,-beta,-alpha,new_depth-reduction,height+1,new_pv,NODE_OPP(node_type),cap_extended,ThreadId); // The move was reduced and fails high; so we research with full depth if (reduced && value >= beta){ value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NODE_OPP(node_type),cap_extended,ThreadId); } } else { // other moves (all PV children) value = -full_search(board,-alpha-1,-alpha,new_depth-reduction,height+1,new_pv,NodeCut,cap_extended,ThreadId); // In case of fail high: // If reduced then we try a research with node_type = NodePV if (value > alpha && reduced){ // && value < beta value = -full_search(board,-beta,-alpha,new_depth-reduction,height+1,new_pv,NodePV,cap_extended,ThreadId); // Still fails high! We research to full depth if (reduced && value >= beta){ value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NodePV,cap_extended,ThreadId); } // If not reduced we research as a PV node } else if (value > alpha){ value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NodePV,cap_extended,ThreadId); } } move_undo(board,move,undo); played[played_nb++] = move; if (value > best_value) { best_value = value; pv_cat(pv,new_pv,move); if (value > alpha) { alpha = value; best_move = move; if (value >= beta){ goto cut; } } } if (node_type == NodeCut) node_type = NodeAll; } // ALL node if (best_value == ValueNone) { // no legal move if (in_check) { ASSERT(board_is_mate(board)); return VALUE_MATE(height); } else { ASSERT(board_is_stalemate(board)); return ValueDraw; } } cut: ASSERT(value_is_ok(best_value)); // move ordering if (best_move != MoveNone) { good_move(best_move,board,depth,height,ThreadId); if (best_value >= beta && !move_is_tactical(best_move,board)) { // check is 204b and d, e ASSERT(played_nb>0&&played[played_nb-1]==best_move); for (i = 0; i < played_nb-1; i++) { move = played[i]; ASSERT(move!=best_move); history_bad(move,board,ThreadId); } history_good(best_move,board,ThreadId); } } // transposition table if (UseTrans && depth >= TransDepth) { trans_move = best_move; trans_depth = depth; trans_flags = TransUnknown; if (best_value > old_alpha) trans_flags |= TransLower; if (best_value < beta) trans_flags |= TransUpper; trans_value = value_to_trans(best_value,height); trans_store(Trans,board->key,trans_move,trans_depth,trans_flags,trans_value); } return best_value; } // full_no_null() static int full_no_null(board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int node_type, int trans_move, int * best_move, bool extended, int ThreadId) { int value, best_value; int move; int new_depth; attack_t attack[1]; sort_t sort[1]; undo_t undo[1]; mv_t new_pv[HeightMax]; bool cap_extended; ASSERT(board!=NULL); ASSERT(range_is_ok(alpha,beta)); ASSERT(depth_is_ok(depth)); ASSERT(height_is_ok(height)); ASSERT(pv!=NULL); ASSERT(node_type==NodePV||node_type==NodeCut||node_type==NodeAll); ASSERT(trans_move==MoveNone||move_is_ok(trans_move)); ASSERT(best_move!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); ASSERT(depth>=1); // init SearchCurrent[ThreadId]->node_nb++; SearchInfo[ThreadId]->check_nb--; PV_CLEAR(pv); if (height > SearchCurrent[ThreadId]->max_depth) SearchCurrent[ThreadId]->max_depth = height; if (SearchInfo[ThreadId]->check_nb <= 0) { SearchInfo[ThreadId]->check_nb += SearchInfo[ThreadId]->check_inc; search_check(ThreadId); } attack_set(attack,board); ASSERT(!ATTACK_IN_CHECK(attack)); *best_move = MoveNone; best_value = ValueNone; // move loop sort_init(sort,board,attack,depth,height,trans_move,ThreadId); while ((move=sort_next(sort,ThreadId)) != MoveNone) { new_depth = full_new_depth(depth,move,board,false,false,height,extended,&cap_extended,ThreadId); move_do(board,move,undo); value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NODE_OPP(node_type),cap_extended,ThreadId); move_undo(board,move,undo); if (value > best_value) { best_value = value; pv_cat(pv,new_pv,move); if (value > alpha) { alpha = value; *best_move = move; if (value >= beta) goto cut; } } } // ALL node if (best_value == ValueNone) { // no legal move => stalemate ASSERT(board_is_stalemate(board)); best_value = ValueDraw; } cut: ASSERT(value_is_ok(best_value)); return best_value; } // full_quiescence() static int full_quiescence(board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int ThreadId) { bool in_check; int old_alpha; int value, best_value; int best_move; int move; int opt_value; attack_t attack[1]; sort_t sort[1]; undo_t undo[1]; mv_t new_pv[HeightMax]; int probe_score, probe_depth; int trans_move, trans_depth, trans_flags, trans_value; entry_t * found_entry; ASSERT(board!=NULL); ASSERT(range_is_ok(alpha,beta)); ASSERT(depth_is_ok(depth)); ASSERT(height_is_ok(height)); ASSERT(pv!=NULL); ASSERT(board_is_legal(board)); ASSERT(depth<=0); // init SearchCurrent[ThreadId]->node_nb++; SearchInfo[ThreadId]->check_nb--; PV_CLEAR(pv); if (height > SearchCurrent[ThreadId]->max_depth) SearchCurrent[ThreadId]->max_depth = height; if (SearchInfo[ThreadId]->check_nb <= 0) { SearchInfo[ThreadId]->check_nb += SearchInfo[ThreadId]->check_inc; search_check(ThreadId); } // draw? if (board_is_repetition(board)) return ValueDraw; /* Interior node recognizer from scorpio by Daniel Shawul -> dont probe at the leaves as this will slow down search For 4/3 pieces probe there also. -> After captures and pawn moves assume exact score and cutoff tree, because we are making progress. Note this is not done only for speed. -> if we are far from root (depth / 2), assume exact score and cutoff tree */ /* if (egbb_is_loaded && board->piece_nb <= 4){ if (probe_bitbases(board, probe_score)){ probe_score = value_from_trans(probe_score,height); return probe_score; } }*/ if (recog_draw(board,ThreadId)) return ValueDraw; // mate-distance pruning if (UseDistancePruning) { // lower bound value = VALUE_MATE(height+2); // does not work if the current position is mate if (value > alpha && board_is_mate(board)) value = VALUE_MATE(height); if (value > alpha) { alpha = value; if (value >= beta) return value; } // upper bound value = -VALUE_MATE(height+1); if (value < beta) { beta = value; if (value <= alpha) return value; } } // transposition table: added by Jerry Donald, about +20 elo self-play trans_move = MoveNone; if (UseTrans) { if (trans_retrieve(Trans,&found_entry,board->key,&trans_move,&trans_depth,&trans_flags,&trans_value)) { trans_value = value_from_trans(trans_value,height); ///////////////////// // Hash hit scheme // ///////////////////// // In case of exact hit, return if this is not a PV node qsearch // In case of upper bound and value <= alpha, return for all node types // In case of lower bound and value >= beta, return for all node types // @tried returning always (~ -10 elo, 4000 games) // @tried returning only in non-PV nodes (~ -5 elo, 4000 games) // @tried doing trans move first (~ - 5 elo, 4000 games) if ((UseExact && beta == alpha+1 && trans_value != ValueNone && TRANS_IS_EXACT(trans_flags)) || (TRANS_IS_LOWER(trans_flags) && trans_value >= beta) || (TRANS_IS_UPPER(trans_flags) && trans_value <= alpha)) { return trans_value; } } } // more init attack_set(attack,board); in_check = ATTACK_IN_CHECK(attack); if (in_check) { ASSERT(depth<0); depth++; // in-check extension } // height limit if (height >= HeightMax-1) return eval(board, alpha, beta, ThreadId); // more init old_alpha = alpha; best_value = ValueNone; best_move = MoveNone; /* if (UseDelta) */ opt_value = +ValueInf; if (!in_check) { // lone-king stalemate? if (simple_stalemate(board)) return ValueDraw; // stand pat value = eval(board, alpha, beta, ThreadId); ASSERT(value>best_value); best_value = value; if (value > alpha) { alpha = value; if (value >= beta) goto cut; } if (UseDelta) { opt_value = value + DeltaMargin; ASSERT(opt_value<+ValueInf); } } // move loop /* cd = CheckDepth; if(cd < 0 && board->piece_size[board->turn] <= 5) cd++; */ sort_init_qs(sort,board,attack, depth>=SearchCurrent[ThreadId]->CheckDepth /* depth>=cd */); while ((move=sort_next_qs(sort)) != MoveNone) { // delta pruning if (UseDelta && beta == old_alpha+1) { // i.e. non-PV if (!in_check && !move_is_check(move,board) && !capture_is_dangerous(move,board)) { ASSERT(move_is_tactical(move,board)); // optimistic evaluation value = opt_value; int to = MOVE_TO(move); int capture = board->square[to]; if (capture != Empty) { value += VALUE_PIECE(capture); } else if (MOVE_IS_EN_PASSANT(move)) { value += ValuePawn; } if (MOVE_IS_PROMOTE(move)) value += ValueQueen - ValuePawn; // pruning if (value <= alpha) { if (value > best_value) { best_value = value; PV_CLEAR(pv); } continue; } } } move_do(board,move,undo); value = -full_quiescence(board,-beta,-alpha,depth-1,height+1,new_pv,ThreadId); move_undo(board,move,undo); if (value > best_value) { best_value = value; pv_cat(pv,new_pv,move); if (value > alpha) { alpha = value; best_move = move; if (value >= beta) goto cut; } } } // ALL node if (best_value == ValueNone) { // no legal move ASSERT(board_is_mate(board)); return VALUE_MATE(height); } cut: // store result in hash table (JD) if (UseTrans) { trans_move = best_move; trans_depth = 0; trans_flags = TransUnknown; if (best_value > old_alpha) trans_flags |= TransLower; if (best_value < beta) trans_flags |= TransUpper; trans_value = value_to_trans(best_value,height); trans_store(Trans,board->key,trans_move,trans_depth,trans_flags,trans_value); } ASSERT(value_is_ok(best_value)); return best_value; } // full_new_depth() static int full_new_depth(int depth, int move, board_t * board, bool single_reply, bool in_pv, int height, bool extended, bool * cap_extended, int ThreadId) { int new_depth; ASSERT(depth_is_ok(depth)); ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(single_reply==true||single_reply==false); ASSERT(in_pv==true||in_pv==false); ASSERT(depth>0); new_depth = depth - 1; *cap_extended = false; if (in_pv && board->square[MOVE_TO(move)] != Empty && !PIECE_IS_PAWN(board->square[MOVE_TO(move)])){ if ((board->piece_size[White] + board->piece_size[Black]) == 3){ return new_depth+1; } else if ((board->piece_size[White] == 3 && board->piece_size[Black] == 2) || (board->piece_size[White] == 2 && board->piece_size[Black] == 3)) return new_depth+1; } if ((single_reply && ExtendSingleReply) //|| (in_pv && MOVE_TO(move) == board->cap_sq // recapture // && see_move(move,board) >= -100 /*|| ABS(VALUE_PIECE(board->square[MOVE_TO(move)])-VALUE_PIECE(board->square[MOVE_FROM(move)])) <= 250 )*/) //|| (in_pv && PIECE_IS_PAWN(MOVE_PIECE(move,board)) // && (PAWN_RANK(MOVE_TO(move),board->turn) == Rank7 || PAWN_RANK(MOVE_TO(move),board->turn) == Rank6)) //|| (in_pv && board->square[MOVE_TO(move)] != PieceNone256 && SearchCurrent[ThreadId]->act_iteration-height >= 6 && see_move(move,board) >= -100) //|| (in_pv && board->square[MOVE_TO(move)] != PieceNone256 && !extended && see_move(move,board) >= -100) //|| (in_pv && mate_threat == true) || move_is_check(move,board) && (in_pv || see_move(move,board) >= -100)) { // @tried no check extension in endgame (~ -5 elo) // @tried no bad SEE check extension in PV (~ -5 elo) return new_depth+1; } if (in_pv && PIECE_IS_PAWN(MOVE_PIECE(move,board))){ if (is_passed(board,MOVE_TO(move))) return new_depth+1; } if (in_pv && board->square[MOVE_TO(move)] != PieceNone256 && !extended && see_move(move,board) >= -100){ *cap_extended = true; return new_depth+1; } ASSERT(new_depth>=0&&new_depth<=depth); return new_depth; } // do_null() static bool do_null(const board_t * board) { ASSERT(board!=NULL); // use null move if the side-to-move has at least one piece return board->piece_size[board->turn] >= 2; // king + one piece } // do_ver() static bool do_ver(const board_t * board) { ASSERT(board!=NULL); // use verification if the side-to-move has at most one piece return board->piece_size[board->turn] <= 3; // king + one piece was 2 } // pv_fill() static void pv_fill(const mv_t pv[], board_t * board) { int move; int trans_move, trans_depth; undo_t undo[1]; ASSERT(pv!=NULL); ASSERT(board!=NULL); ASSERT(UseTrans); move = *pv; if (move != MoveNone && move != MoveNull) { move_do(board,move,undo); pv_fill(pv+1,board); move_undo(board,move,undo); trans_move = move; trans_depth = -127; // HACK trans_store(Trans,board->key,trans_move,trans_depth,TransUnknown,-ValueInf); } } // move_is_dangerous() static bool move_is_dangerous(int move, const board_t * board) { int piece; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); piece = MOVE_PIECE(move,board); if (PIECE_IS_PAWN(piece) && is_passed(board,MOVE_TO(move)) /*PAWN_RANK(MOVE_TO(move),board->turn) >= Rank7*/) { return true; } return false; } // capture_is_dangerous() static bool capture_is_dangerous(int move, const board_t * board) { int piece, capture; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); piece = MOVE_PIECE(move,board); if (PIECE_IS_PAWN(piece) && PAWN_RANK(MOVE_TO(move),board->turn) >= Rank7) { return true; } capture = move_capture(move,board); if (PIECE_IS_QUEEN(capture)) return true; if (PIECE_IS_PAWN(capture) && PAWN_RANK(MOVE_TO(move),board->turn) <= Rank2) { return true; } return false; } // simple_stalemate() static bool simple_stalemate(const board_t * board) { int me, opp; int king; int opp_flag; int from, to; int capture; const inc_t * inc_ptr; int inc; ASSERT(board!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); // lone king? me = board->turn; if (board->piece_size[me] != 1 || board->pawn_size[me] != 0) return false; // no // king in a corner? king = KING_POS(board,me); if (king != A1 && king != H1 && king != A8 && king != H8) return false; // no // init opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); // king can move? from = king; for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; capture = board->square[to]; if (capture == Empty || FLAG_IS(capture,opp_flag)) { if (!is_attacked(board,to,opp)) return false; // legal king move } } // no legal move ASSERT(board_is_stalemate((board_t*)board)); return true; } static bool is_passed(const board_t * board, int to) { int t2; int me, opp; int file, rank; me = board->turn; opp = COLOUR_OPP(me); file = SQUARE_FILE(to); rank = PAWN_RANK(to,me); t2 = board->pawn_file[me][file] | BitRev[board->pawn_file[opp][file]]; // passed pawns if ((t2 & BitGT[rank]) == 0) { if (((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitGT[rank]) == 0) { return true; } } return false; } // end of search_full.cpp toga2-3.0.0.1SE1/src/Makefile.orig0000644000175000017500000000204411125213426015743 0ustar oliveroliver # files EXE = cyclone2 OBJS = move.o main.o hash.o see.o config.o search_root.o util.o pawn.o sort.o \ valid_move.o input.o piece.o material.o check.o evasion.o make_move.o \ board.o move_list.o fen.o values.o search.o interface.o draw.o square.o \ evaluate.o position.o random.o attack.o pv.o distance.o transposition.o \ probe.o move_gen.o # rules all: $(EXE) .depend clean: $(RM) *.o .depend gmon.out $(EXE) $(EXE).intel *~ # general CXX = gcc CXXFLAGS = -pipe LDFLAGS = -lm -ldl -lpthread # C++ CXXFLAGS += -O3 -fno-exceptions -fno-rtti -Wall # optimisation CXXFLAGS += -fstrict-aliasing CXXFLAGS += -fomit-frame-pointer # CXXFLAGS += -march=athlon-xp # SELECT ME # CXXFLAGS += -march=pentium4 # profiling #CXXFLAGS += -fprofile-generate #LDFLAGS += -fprofile-generate #CXXFLAGS += -fprofile-use # strip LDFLAGS += -s # dependencies $(EXE): $(OBJS) $(CXX) $(LDFLAGS) -o $@ $(OBJS) .depend: $(CXX) -MM $(OBJS:.o=.cpp) > $@ include .depend toga2-3.0.0.1SE1/src/probe.h0000644000175000017500000000121311125217316014623 0ustar oliveroliver // probe.h // includes // constants // macros // types typedef int (*PPROBE_EGBB) (int player, int w_king, int b_king, int piece1, int square1, int piece2, int square2, int piece3, int square3); typedef void (*PLOAD_EGBB) (char* path,int cache_size,int load_options); static PPROBE_EGBB probe_egbb; // "constants" #define _NOTFOUND 99999 #define WIN_SCORE 3000 #define WIN_PLY 40 // variables extern bool egbb_is_loaded; // functions extern int LoadEgbbLibrary(char* main_path,uint32 egbb_cache_size); extern int probe_bitbases(board_t * board, int& score); // end of probe.h toga2-3.0.0.1SE1/src/move_legal.cpp0000644000175000017500000001116111125217322016161 0ustar oliveroliver // move_legal.cpp // includes #include "attack.h" #include "colour.h" #include "fen.h" #include "list.h" #include "move.h" #include "move_do.h" #include "move_gen.h" #include "move_legal.h" #include "piece.h" #include "square.h" #include "util.h" // prototypes static bool move_is_pseudo_debug (int move, board_t * board); // functions // move_is_pseudo() bool move_is_pseudo(int move, board_t * board) { int me, opp; int from, to; int piece, capture; int inc, delta; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); // special cases if (MOVE_IS_SPECIAL(move)) { return move_is_pseudo_debug(move,board); } ASSERT((move&~07777)==0); // init me = board->turn; opp = COLOUR_OPP(board->turn); // from from = MOVE_FROM(move); ASSERT(SQUARE_IS_OK(from)); piece = board->square[from]; if (!COLOUR_IS(piece,me)) return false; ASSERT(piece_is_ok(piece)); // to to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); capture = board->square[to]; if (COLOUR_IS(capture,me)) return false; // move if (PIECE_IS_PAWN(piece)) { if (SQUARE_IS_PROMOTE(to)) return false; inc = PAWN_MOVE_INC(me); delta = to - from; ASSERT(delta_is_ok(delta)); if (capture == Empty) { // pawn push if (delta == inc) return true; if (delta == (2*inc) && PAWN_RANK(from,me) == Rank2 && board->square[from+inc] == Empty) { return true; } } else { // pawn capture if (delta == (inc-1) || delta == (inc+1)) return true; } } else { if (PIECE_ATTACK(board,piece,from,to)) return true; } return false; } // quiet_is_pseudo() bool quiet_is_pseudo(int move, board_t * board) { int me, opp; int from, to; int piece; int inc, delta; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); // special cases if (MOVE_IS_CASTLE(move)) { return move_is_pseudo_debug(move,board); } else if (MOVE_IS_SPECIAL(move)) { return false; } ASSERT((move&~07777)==0); // init me = board->turn; opp = COLOUR_OPP(board->turn); // from from = MOVE_FROM(move); ASSERT(SQUARE_IS_OK(from)); piece = board->square[from]; if (!COLOUR_IS(piece,me)) return false; ASSERT(piece_is_ok(piece)); // to to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); if (board->square[to] != Empty) return false; // capture // move if (PIECE_IS_PAWN(piece)) { if (SQUARE_IS_PROMOTE(to)) return false; inc = PAWN_MOVE_INC(me); delta = to - from; ASSERT(delta_is_ok(delta)); // pawn push if (delta == inc) return true; if (delta == (2*inc) && PAWN_RANK(from,me) == Rank2 && board->square[from+inc] == Empty) { return true; } } else { if (PIECE_ATTACK(board,piece,from,to)) return true; } return false; } // pseudo_is_legal() bool pseudo_is_legal(int move, board_t * board) { int me, opp; int from, to; int piece; bool legal; int king; undo_t undo[1]; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // slow test for en-passant captures if (MOVE_IS_EN_PASSANT(move)) { move_do(board,move,undo); legal = !IS_IN_CHECK(board,me); move_undo(board,move,undo); return legal; } // king moves (including castle) if (PIECE_IS_KING(piece)) { legal = !is_attacked(board,to,opp); if (DEBUG) { ASSERT(board->square[from]==piece); board->square[from] = Empty; ASSERT(legal==!is_attacked(board,to,opp)); board->square[from] = piece; } return legal; } // pins if (is_pinned(board,from,me)) { king = KING_POS(board,me); return DELTA_INC_LINE(king-to) == DELTA_INC_LINE(king-from); // does not discover the line } return true; } // move_is_pseudo_debug() static bool move_is_pseudo_debug(int move, board_t * board) { list_t list[1]; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); gen_moves(list,board); return list_contain(list,move); } // end of move_legal.cpp toga2-3.0.0.1SE1/src/sort.h0000644000175000017500000000247511125217316014516 0ustar oliveroliver // sort.h #ifndef SORT_H #define SORT_H // includes #include "attack.h" #include "board.h" #include "list.h" #include "util.h" // types struct sort_t { int depth; int height; int trans_killer; int killer_1; int killer_2; int gen; int test; int pos; int value; int valuePV; int capture_nb; board_t * board; const attack_t * attack; list_t list[1]; list_t bad[1]; }; // functions extern void sort_init (int ThreadId); extern void sort_init (sort_t * sort, board_t * board, const attack_t * attack, int depth, int height, int trans_killer, int ThreadId); extern int sort_next (sort_t * sort, int ThreadId); extern void sort_init_qs (sort_t * sort, board_t * board, const attack_t * attack, bool check); extern int sort_next_qs (sort_t * sort); extern void good_move (int move, const board_t * board, int depth, int height, int ThreadId); extern void history_good (int move, const board_t * board, int ThreadId); extern void history_bad (int move, const board_t * board, int ThreadId); extern void history_reset (int move, const board_t * board, int ThreadId); extern void note_moves (list_t * list, const board_t * board, int height, int trans_killer, int ThreadId); #endif // !defined SORT_H // end of sort.h toga2-3.0.0.1SE1/src/value.h0000644000175000017500000000230311125217324014630 0ustar oliveroliver // value.h #ifndef VALUE_H #define VALUE_H // includes #include "piece.h" #include "util.h" // constants const int ValuePawn = 100; // was 100 const int ValueKnight = 325; // was 300 const int ValueBishop = 325; // was 300 const int ValueRook = 500; // was 500 const int ValueQueen = 1000; // was 900 const int ValueKing = 10000; // was 10000 const int ValueNone = -32767; const int ValueDraw = 0; const int ValueMate = 30000; const int ValueWin = 3000; const int ValuePly = 40; const int ValueInf = ValueMate; const int ValueEvalInf = ValueMate - 256; // handle mates upto 255 plies // macros #define VALUE_MATE(height) (-ValueMate+(height)) #define VALUE_PIECE(piece) (ValuePiece[piece]) // variables extern int ValuePiece[PieceNb]; // functions extern void value_init (); extern bool value_is_ok (int value); extern bool range_is_ok (int min, int max); extern bool value_is_mate (int value); extern int value_to_trans (int value, int height); extern int value_from_trans (int value, int height); extern int value_to_mate (int value); #endif // !defined VALUE_H // end of value.h toga2-3.0.0.1SE1/src/copying Version 2 June 1991.txt0000644000175000017500000004365511125213420020562 0ustar oliveroliver GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.