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 if (height > 2 && move == Killer[ThreadId][height-2][0]) { // killer 1 value = KillerScore - 1; } else if (height > 2 && move == Killer[ThreadId][height-2][1]) { // killer 2 value = KillerScore - 3; } else { // quiet move value = quiet_move_value(move,board,ThreadId); } return value; }
static void update_cm_stats(Stack *ss, Piece pc, Square s, int bonus) { if (move_is_ok((ss-1)->currentMove)) cms_update(*(ss-1)->history, pc, s, bonus); if (move_is_ok((ss-2)->currentMove)) cms_update(*(ss-2)->history, pc, s, bonus); if (move_is_ok((ss-4)->currentMove)) cms_update(*(ss-4)->history, pc, s, bonus); if (move_is_ok((ss-6)->currentMove)) cms_update(*(ss-6)->history, pc, s, bonus); }
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) >= 0; }
static void move_step(int move) { board_t board[1]; char move_string[256]; ASSERT(move_is_ok(move)); // log game_get_board(Game,board); if (XB->ics || (move != MoveNone && move_is_legal(move,board))) { move_to_san(move,board,move_string,sizeof(move_string)); my_log("POLYGLOT MOVE %s\n",move_string); } else { move_to_can(move,board,move_string,sizeof(move_string)); my_log("POLYGLOT ILLEGAL MOVE \"%s\"\n",move_string); board_disp(board); //since we have threads my_fatal is not enough,1 thread will wait for xboard to end the game //stuff illegal move in the comment as well,not everybody logs all the time. if(board->turn==White) xboard_send(XBoard,"0-1 {polyglot: %s illegal engine move white}\n",move_string); else xboard_send(XBoard,"1-0 {polyglot: %s illegal engine move black}\n",move_string); my_fatal("move_step(): illegal move \"%s\"\n",move_string); } // play the move game_add_move(Game,move); //board_update(); }
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; }
static int history_prob(int move, const board_t * board, int ThreadId) { int value; unsigned int index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board) || see_move(move,board) < 0 || move_is_under_promote(move)); index = history_index(move,board); ASSERT(HistHit[index]<=HistTot[index]); ASSERT(HistTot[index]<HistTotMax); // int * int assumed to be int by C++, large values and overflows need to use double on the interim product. value = int(double(double(HistHit[index]) * HistoryMax) / HistTot[index]); // // for uint16 or short or unsigned short the simple formula is OK. // value = ( ( (HistHit[index]) * HistoryMax) / HistTot[index]); // HistoryMax instead ASSERT(value>=1 && value<=16384); return value; }
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; }
void sort_init_qs(sort_t * sort, board_t * board, const attack_t * attack, int depth, int node_type, int trans_killer) { ASSERT(sort!=NULL); ASSERT(board!=NULL); ASSERT(attack!=NULL); ASSERT(depth_is_ok(depth)); ASSERT(node_type==NodePV||node_type==NodeCut||node_type==NodeAll); ASSERT(trans_killer==MoveNone||move_is_ok(trans_killer)); sort->board = board; sort->attack = attack; sort->depth = depth; sort->value = node_type; // HACK sort->trans_killer = trans_killer; if (ATTACK_IN_CHECK(sort->attack)) { sort->gen = PosEvasionQS; } else if (depth >= 0) { sort->gen = PosCheckQS; } else { sort->gen = PosCaptureQS; } LIST_CLEAR(sort->list); sort->pos = 0; }
static int history_prob(int move, const board_t * board) { int value; int index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!MOVE_IS_TACTICAL(move,board)); index = history_index(move,board); #if DEBUG if (thread_number() == 1) { ASSERT(HistHit[index]<=HistTot[index]); ASSERT(HistTot[index]<HistoryMax); } #endif value = (HistHit[index] * 16384) / HistTot[index]; if (value > 16384) value = 16384; // HACK: Thread related ASSERT(value>=0&&value<=16384); return value; }
static int quiet_move_value(int move, const board_t * board) { int value; int index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!MOVE_IS_TACTICAL(move,board)); index = history_index(move,board); value = History[index]; #if DEBUG if (thread_number() > 1) { ASSERT(value<=HistoryValue+8192&&value>=-HistoryValue-8192); } else { ASSERT(value<=HistoryValue&&value>=-HistoryValue); } #endif if (UseMoveEval) { if (value > HistoryScore) value += HistoryEvalMax; value += HISTORY_EVAL(HistEval[index]); } value /= HeightFull; ASSERT(value>=BadScore+100&&value<KillerScore-4); return value; }
void good_move(int move, const board_t * board, int depth, int height) { int 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[height][0] != move) { Killer[height][1] = Killer[height][0]; Killer[height][0] = move; } ASSERT(Killer[height][0]==move); ASSERT(Killer[height][1]!=move); // history index = history_index(move,board); History[index] += HISTORY_INC(depth); if (History[index] >= HistoryMax) { for (i = 0; i < HistorySize; i++) { History[i] = (History[i] + 1) / 2; } } }
void move_eval(const board_t * board, int eval) { int index; int best_value, value; int move; ASSERT(board!=NULL); ASSERT(value_is_ok(eval)); move = board->move; ASSERT(move_is_ok(move)); // exceptions if ((move & (1 << 15)) != 0) return; if (MOVE_TO(move) == board->cap_sq) return; if (MOVE_IS_CASTLE(move)) return; ASSERT(!MOVE_IS_PROMOTE(move)); ASSERT(!MOVE_IS_EN_PASSANT(move)); ASSERT(board->cap_sq==Empty); ASSERT(!board_is_check(board)); index = PIECE_TO_12(board->square[MOVE_TO(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move)); ASSERT(index>=0&&index<HistorySize); if (eval > ValueQueen) { value = ValueQueen; } else if (eval < -ValueQueen) { value = -ValueQueen; } else { value = eval; } best_value = HistEval[index]; ASSERT(best_value<=HistoryEvalMax); ASSERT(best_value>=-HistoryEvalMax); if (value >= best_value) { if (value == HistoryEvalValue) value++; HistEval[index] = value; } else { if (HistEval[index] > -ValueQueen) { if (best_value == HistoryEvalValue+1) { HistEval[index] -= 2; } else { HistEval[index]--; } } } ASSERT(HistEval[index]!=HistoryEvalValue); ASSERT(HistEval[index]<=HistoryEvalMax); ASSERT(HistEval[index]>=-HistoryEvalMax); }
static void move_step(int move) { board_t board[1]; char move_string[256]; ASSERT(move_is_ok(move)); // log game_get_board(Game,board); if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,256); my_log("POLYGLOT MOVE %s\n",move_string); } else { move_to_can(move,board,move_string,256); my_log("POLYGLOT ILLEGAL MOVE \"%s\"\n",move_string); board_disp(board); my_fatal("move_step(): illegal move \"%s\"\n",move_string); } // play the move game_add_move(Game,move); board_update(); }
static bool ponder_move_is_ok(int move) { int status; board_t board[1]; ASSERT(move==MoveNone||move_is_ok(move)); // legal ponder move? if (move == MoveNone) return false; game_get_board(Game,board); if (!move_is_legal(move,board)) return false; // UCI-legal resulting position? game_add_move(Game,move); game_get_board(Game,board); status = game_status(Game); game_rem_move(Game); if (status != PLAYING) return false; // game ended if (option_get_bool("Book") && is_in_book(board)) { return false; } return true; }
void history_good(int move, const board_t * board, int ThreadId) { unsigned int index; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!move_is_tactical(move,board)); // if ( move_is_tactical(move,board)) return; // history index = history_index(move,board); HistHit[index]++; HistTot[index]++; if (HistTot[index] >= HistTotMax) { HistHit[index] = (HistHit[index] + 1) / 2; HistTot[index] = (HistTot[index] + 1) / 2; } ASSERT(HistHit[index]<=HistTot[index]); ASSERT(HistTot[index]<HistTotMax); }
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; }
void move_undo(int move, const undo_t * undo) { int me; int from, to; int piece,pos; ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); // init me = undo->turn; from = MOVE_FROM(move); to = MOVE_TO(move); piece = Square[to]; pos=piece & 31; ASSERT(COLOUR_IS(piece,me)); Square[from]=piece; Piece[pos]=from; BitRanks[from>>4] ^= g_BitRankMask[from]; BitFiles[from & 0xf]^= g_BitFileMask[from]; if(undo->capture)//吃子更新 { Square[to]=undo->capture_piece; Piece[undo->capture_piece & 31]=to; Piece_size[PIECE_COLOUR(undo->capture_piece)]++; Number[PieceTo32[undo->capture_piece & 31]]++; }else { Square[to]=Empty; BitRanks[to>>4] ^= g_BitRankMask[to]; BitFiles[to&0xf]^= g_BitFileMask[to]; } Turn = undo->turn; Opening = undo->opening; Endgame = undo->endgame; Key = undo->key; Lock = undo->lock; Sp--; }
static int move_value_simple(int move, const board_t * board, int trans_killer) { int value; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); 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 = GoodScore + mvv_lva(move,board); } else { // quiet move value = quiet_move_value(move,board); } return value; }
static bool move_is_legal_debug(int move, const board_t * board) { list_t list[1]; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); gen_legal_moves(list,board); return list_contain(list,move); }
bool move_is_pseudo(int move, const board_t * board) { list_t list[1]; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); gen_moves(list,board); return list_contain(list,move); }
void list_add(list_t * list, int move, int value) { ASSERT(list_is_ok(list)); ASSERT(move_is_ok(move)); ASSERT(value>=-32767&&value<=+32767); ASSERT(list->size<ListSize-1); list->move[list->size] = move; list->value[list->size] = value; list->size++; }
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); } }
bool line_is_ok(const move_t line[]) { int move; if (line == NULL) return false; while ((move = *line++) != MoveNone) { if (!move_is_ok(move)) return false; } return true; }
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); }
bool move_is_legal(int move, const board_t * board) { bool legal; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); legal = move_is_pseudo(move,board) && pseudo_is_legal(move,board); ASSERT(legal==move_is_legal_debug(move,board)); return legal; }
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; }
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; }
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); }
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); }
static void comp_move(int move) { board_t board[1]; char string[256]; ASSERT(move_is_ok(move)); ASSERT(State->state==THINK); ASSERT(!XB->analyse); if(option_get_bool(Option,"RepeatPV")) send_pv(); // to update time and nodes // send the move game_get_board(Game,board); if (move_is_castle(move,board) && option_get_bool(Option,"Chess960")) { if (!move_to_san(move,board,string,256)) my_fatal("comp_move(): move_to_san() failed\n"); // O-O/O-O-O } else { if (!move_to_can(move,board,string,256)) my_fatal("comp_move(): move_to_can() failed\n"); } gui_send(GUI,"move %s",string); // resign? if (option_get_bool(Option,"Resign") && Uci->root_move_nb > 1) { if (Uci->best_score <= -abs(option_get_int(Option,"ResignScore"))) { State->resign_nb++; my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":""); if (State->resign_nb >= option_get_int(Option,"ResignMoves")) { my_log("POLYGLOT *** RESIGN ***\n"); gui_send(GUI,"resign"); } } else { if (State->resign_nb > 0) my_log("POLYGLOT resign reset (State->resign_nb=%d)\n",State->resign_nb); State->resign_nb = 0; } } // play the move move_step(move); no_mess(move); }